pingcap / tidb

TiDB - the open-source, cloud-native, distributed SQL database designed for modern applications.
https://pingcap.com
Apache License 2.0
37.36k stars 5.85k forks source link

DATA RACE github.com/tikv/client-go/v2/internal/unionstore/rbt.(*RBT) #56178

Open hawkingrei opened 2 months ago

hawkingrei commented 2 months ago

Bug Report

Please answer these questions before submitting your issue. Thanks!

1. Minimal reproduce step (Required)

2. What did you expect to see? (Required)

3. What did you see instead (Required)

==================
WARNING: DATA RACE
Read at 0x00c00833a831 by goroutine 15338:
  github.com/tikv/client-go/v2/internal/unionstore/rbt.(*RBT).Dirty()
      external/com_github_tikv_client_go_v2/internal/unionstore/rbt/rbt.go:310 +0x57
  github.com/tikv/client-go/v2/internal/unionstore.(*rbtDBWithContext).Dirty()
      <autogenerated>:1 +0x17
  github.com/tikv/client-go/v2/txnkv/transaction.(*KVTxn).IsReadOnly()
      external/com_github_tikv_client_go_v2/txnkv/transaction/txn.go:1676 +0x5e
  github.com/pingcap/tidb/pkg/store/driver/txn.(*tikvTxn).IsReadOnly()
      <autogenerated>:1 +0x3e
  github.com/pingcap/tidb/pkg/session.(*LazyTxn).IsReadOnly()
      <autogenerated>:1 +0x46
  github.com/pingcap/tidb/pkg/executor.(*PointGetExecutor).get()
      pkg/executor/point_get.go:636 +0xe3
  github.com/pingcap/tidb/pkg/executor.(*PointGetExecutor).getAndLock()
      pkg/executor/point_get.go:549 +0x2c4
  github.com/pingcap/tidb/pkg/executor.(*PointGetExecutor).Next()
      pkg/executor/point_get.go:382 +0x1136
  github.com/pingcap/tidb/pkg/executor/internal/exec.Next()
      pkg/executor/internal/exec/executor.go:451 +0x418
  github.com/pingcap/tidb/pkg/executor.(*SelectLockExec).Next()
      pkg/executor/executor.go:1190 +0xde
  github.com/pingcap/tidb/pkg/executor/internal/exec.Next()
      pkg/executor/internal/exec/executor.go:451 +0x418
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).resultPuller()
      pkg/executor/unionexec/union.go:164 +0x969
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).initialize.func1()
      pkg/executor/unionexec/union.go:117 +0x5d
Previous write at 0x00c00833a831 by goroutine 15337:
  github.com/tikv/client-go/v2/internal/unionstore/rbt.(*RBT).Set()
      external/com_github_tikv_client_go_v2/internal/unionstore/rbt/rbt.go:344 +0x2b1
  github.com/tikv/client-go/v2/internal/unionstore.(*rbtDBWithContext).set()
      external/com_github_tikv_client_go_v2/internal/unionstore/memdb_rbt.go:54 +0x16e
  github.com/tikv/client-go/v2/internal/unionstore.(*rbtDBWithContext).UpdateFlags()
      external/com_github_tikv_client_go_v2/internal/unionstore/memdb_rbt.go:59 +0x94
  github.com/tikv/client-go/v2/txnkv/transaction.(*KVTxn).lockKeys()
      external/com_github_tikv_client_go_v2/txnkv/transaction/txn.go:1524 +0x2aa2
  github.com/tikv/client-go/v2/txnkv/transaction.(*KVTxn).LockKeysFunc()
      external/com_github_tikv_client_go_v2/txnkv/transaction/txn.go:1207 +0x1c6
  github.com/pingcap/tidb/pkg/store/driver/txn.(*tikvTxn).LockKeysFunc()
      pkg/store/driver/txn/txn_driver.go:106 +0x174
  github.com/pingcap/tidb/pkg/session.(*LazyTxn).LockKeysFunc()
      pkg/session/txn.go:497 +0x377
  github.com/pingcap/tidb/pkg/session.(*LazyTxn).LockKeys()
      pkg/session/txn.go:472 +0x84
  github.com/pingcap/tidb/pkg/executor.doLockKeys()
      pkg/executor/executor.go:1312 +0x30c
  github.com/pingcap/tidb/pkg/executor.(*SelectLockExec).Next()
      pkg/executor/executor.go:1241 +0x82e
  github.com/pingcap/tidb/pkg/executor/internal/exec.Next()
      pkg/executor/internal/exec/executor.go:451 +0x418
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).resultPuller()
      pkg/executor/unionexec/union.go:164 +0x969
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).initialize.func1()
      pkg/executor/unionexec/union.go:117 +0x5d
Goroutine 15338 (running) created at:
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).initialize()
      pkg/executor/unionexec/union.go:117 +0x52a
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).Next()
      pkg/executor/unionexec/union.go:190 +0xb7
  github.com/pingcap/tidb/pkg/executor/internal/exec.Next()
      pkg/executor/internal/exec/executor.go:451 +0x418
  github.com/pingcap/tidb/pkg/executor/aggregate.(*HashAggExec).fetchChildData()
      pkg/executor/aggregate/agg_hash_executor.go:482 +0x2b8
  github.com/pingcap/tidb/pkg/executor/aggregate.(*HashAggExec).prepare4ParallelExec.func3()
      pkg/executor/aggregate/agg_hash_executor.go:561 +0x5d
Goroutine 15337 (finished) created at:
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).initialize()
      pkg/executor/unionexec/union.go:117 +0x52a
  github.com/pingcap/tidb/pkg/executor/unionexec.(*UnionExec).Next()
      pkg/executor/unionexec/union.go:190 +0xb7
  github.com/pingcap/tidb/pkg/executor/internal/exec.Next()
      pkg/executor/internal/exec/executor.go:451 +0x418
  github.com/pingcap/tidb/pkg/executor/aggregate.(*HashAggExec).fetchChildData()
      pkg/executor/aggregate/agg_hash_executor.go:482 +0x2b8
  github.com/pingcap/tidb/pkg/executor/aggregate.(*HashAggExec).prepare4ParallelExec.func3()
      pkg/executor/aggregate/agg_hash_executor.go:561 +0x5d
================== 

4. What is your TiDB version? (Required)

hawkingrei commented 2 months ago

https://tiprow.hawkingrei.com/view/gs/pingcapprow/logs/tidb_data_race/1836765267791712256#1:build-log.txt%3A30619

cfzjywxk commented 2 months ago

@you06 Is this introduced by the recent refactor?

you06 commented 1 month ago

@you06 Is this introduced by the recent refactor?

This is not introduced by the refactor, I made a reproduce test and found that this race also happens in TiDB 8.1

func TestMemDBRaceInUnionExec(t *testing.T) {
    store := testkit.CreateMockStore(t)
    tk := testkit.NewTestKit(t, store)
    tk.MustExec("use test")
    tables := 5
    for i := 0; i < tables; i++ {
        tk.MustExec(fmt.Sprintf("create table t%d(id int primary key, v int)", i))
    }

    tk.MustExec("insert into t0 values(1, 1), (2, 2), (3, 3), (4, 4)")
    for i := 1; i < tables; i++ {
        tk.MustExec(fmt.Sprintf("insert into t%d select * from t0", i))
    }

    tk.MustExec("set tidb_pessimistic_txn_fair_locking=0")
    for i := 0; i < 1001; i++ {
        tk.MustExec("begin pessimistic")
        tk.MustQuery(`select * from t0 where id = 1 for update union
select * from t1 where id = 1 for update union
select * from t2 where id = 1 for update union
select * from t3 where id = 1 for update union
select * from t4 where id = 1 for update`)
        tk.MustExec("rollback")
    }
}