pingcap / pingcap/tidb

Lock may not be pushed down to point get / batch point get in some cases

Open
#35,524 3 comments 0 reactions 1 assignee Claimed by @SpadeA-Tang View on GitHub
affects-5.0 affects-5.1 affects-5.2 affects-5.3 affects-5.4 affects-6.0 affects-6.1 severity/moderate sig/planner sig/transaction type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report
![image](https://user-images.githubusercontent.com/71589810/174562571-91331ead-8684-4c87-bd58-247a84d1c743.png)
The condition `len(p.Children()) > 1` can skip some cases even point get/batch point get exists.
For example, in the query statment `select * from t where id=1 for update union all select * from t where id = 2 for update`, the lock cannot be pushed down to point get as union all has two children.

If the lock is not pushed down to point get/batch point get, keys will not be locked in `lockKeyIfNeeded` (if the lock is push down to the point get/ batch point get, we should lock the keys here even though they are not exists).

Below is a case that can be easily reproduced.

### 1. Minimal reproduce step (Required)

```
store, _, clean := testkit.CreateMockStoreAndDomain(t)
defer clean()

tk := testkit.NewTestKit(t, store)

tk2 := testkit.NewTestKit(t, store)

tk.MustExec("use test")
tk2.MustExec("use test")
tk.MustExec("create table t (id int primary key, v int)")

tk.MustExec("begin pessimistic")
tk.MustExec("select * from t where id=1 for update union all select * from t where id = 2 for update")
tk2.MustExec("insert into t values (1, 1), (2,2)")

tk.MustExec("rollback")
```

### 2. What did you expect to see? (Required)
The test complets.

### 3. What did you see instead (Required)
Blocked at the final 2 line.

### 4. What is your TiDB version? (Required)
cd731af05a5446bb8dcba83f0e163176c75f5cea

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.