You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
4.2 KiB
124 lines
4.2 KiB
// Copyright 2019-present, PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package mocktikv_test
|
|
|
|
import (
|
|
"context"
|
|
|
|
. "github.com/pingcap/check"
|
|
"github.com/pingcap/errors"
|
|
"github.com/pingcap/kvproto/pkg/kvrpcpb"
|
|
"github.com/pingcap/parser/model"
|
|
"github.com/pingcap/tidb/domain"
|
|
"github.com/pingcap/tidb/kv"
|
|
"github.com/pingcap/tidb/session"
|
|
"github.com/pingcap/tidb/store/mockstore"
|
|
"github.com/pingcap/tidb/store/mockstore/mocktikv"
|
|
"github.com/pingcap/tidb/tablecodec"
|
|
"github.com/pingcap/tidb/util/testkit"
|
|
)
|
|
|
|
var _ = Suite(&testExecutorSuite{})
|
|
|
|
type testExecutorSuite struct {
|
|
cluster *mocktikv.Cluster
|
|
store kv.Storage
|
|
mvccStore mocktikv.MVCCStore
|
|
dom *domain.Domain
|
|
}
|
|
|
|
func (s *testExecutorSuite) SetUpSuite(c *C) {
|
|
s.cluster = mocktikv.NewCluster()
|
|
mocktikv.BootstrapWithSingleStore(s.cluster)
|
|
s.mvccStore = mocktikv.MustNewMVCCStore()
|
|
store, err := mockstore.NewMockTikvStore(
|
|
mockstore.WithCluster(s.cluster),
|
|
mockstore.WithMVCCStore(s.mvccStore),
|
|
)
|
|
c.Assert(err, IsNil)
|
|
s.store = store
|
|
session.SetSchemaLease(0)
|
|
session.DisableStats4Test()
|
|
s.dom, err = session.BootstrapSession(s.store)
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *testExecutorSuite) TearDownSuite(c *C) {
|
|
s.dom.Close()
|
|
s.store.Close()
|
|
}
|
|
|
|
func (s *testExecutorSuite) TestResolvedLargeTxnLocks(c *C) {
|
|
// This test checks the resolve lock functionality.
|
|
// When a txn meets the lock of a large transaction, it should not block by the
|
|
// lock.
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
tk.MustExec("use test")
|
|
tk.MustExec("create table t (id int primary key, val int)")
|
|
dom := domain.GetDomain(tk.Se)
|
|
schema := dom.InfoSchema()
|
|
tbl, err := schema.TableByName(model.NewCIStr("test"), model.NewCIStr("t"))
|
|
c.Assert(err, IsNil)
|
|
|
|
tk.MustExec("insert into t values (1, 1)")
|
|
|
|
oracle := s.store.GetOracle()
|
|
tso, err := oracle.GetTimestamp(context.Background())
|
|
c.Assert(err, IsNil)
|
|
|
|
key := tablecodec.EncodeRowKeyWithHandle(tbl.Meta().ID, 1)
|
|
pairs := s.mvccStore.Scan(key, nil, 1, tso, kvrpcpb.IsolationLevel_SI, nil)
|
|
c.Assert(pairs, HasLen, 1)
|
|
c.Assert(pairs[0].Err, IsNil)
|
|
|
|
// Simulate a large txn (holding a pk lock with large TTL).
|
|
// Secondary lock 200ms, primary lock 100s
|
|
mocktikv.MustPrewriteOK(c, s.mvccStore, mocktikv.PutMutations("primary", "value"), "primary", tso, 100000)
|
|
mocktikv.MustPrewriteOK(c, s.mvccStore, mocktikv.PutMutations(string(key), "value"), "primary", tso, 200)
|
|
|
|
// Simulate the action of reading meet the lock of a large txn.
|
|
// The lock of the large transaction should not block read.
|
|
// The first time, this query should meet a lock on the secondary key, then resolve lock.
|
|
// After that, the query should read the previous version data.
|
|
tk.MustQuery("select * from t").Check(testkit.Rows("1 1"))
|
|
|
|
// Cover BatchGet.
|
|
tk.MustQuery("select * from t where id in (1)").Check(testkit.Rows("1 1"))
|
|
|
|
// Cover PointGet.
|
|
tk.MustExec("begin")
|
|
tk.MustQuery("select * from t where id = 1").Check(testkit.Rows("1 1"))
|
|
tk.MustExec("rollback")
|
|
|
|
// And check the large txn is still alive.
|
|
pairs = s.mvccStore.Scan([]byte("primary"), nil, 1, tso, kvrpcpb.IsolationLevel_SI, nil)
|
|
c.Assert(pairs, HasLen, 1)
|
|
_, ok := errors.Cause(pairs[0].Err).(*mocktikv.ErrLocked)
|
|
c.Assert(ok, IsTrue)
|
|
}
|
|
|
|
func (s *testExecutorSuite) TestIssue15662(c *C) {
|
|
tk := testkit.NewTestKit(c, s.store)
|
|
|
|
tk.MustExec("use test")
|
|
|
|
tk.MustExec("create table V (id int primary key, col_int int)")
|
|
tk.MustExec("insert into V values (1, 8)")
|
|
|
|
tk.MustExec("create table F (id int primary key, col_int int)")
|
|
tk.MustExec("insert into F values (1, 8)")
|
|
|
|
tk.MustQuery("select table1.`col_int` as field1, table1.`col_int` as field2 from V as table1 left join F as table2 on table1.`col_int` = table2.`col_int` order by field1, field2 desc limit 2").
|
|
Check(testkit.Rows("8 8"))
|
|
}
|
|
|