pingcap / pingcap/tidb

Possible MySQL compatibility issue: UPDATE does not wait for a concurrent uncommitted INSERT under REPEATABLE READ

Open
#68,932 4 comments 0 reactions 0 assignees View on GitHub
contribution first-time-contributor may-affects-7.5 may-affects-8.1 may-affects-8.5 severity/major sig/transaction type/bug
Dominant language
Go
Stars
40.5k
Forks
6.2k
PR merge metrics
PR metrics pending

Description

## Bug Report

Please answer these questions before submitting your issue. Thanks!

### 1. Minimal reproduce step (Required)
Here is the test case:
step1: create the initial table t0
```sql
/* init */ DROP TABLE IF EXISTS t0;
/* init */ CREATE TABLE t0(c0 INT);
/* init */ INSERT INTO t0(c0) VALUES(1);
/* init */ INSERT INTO t0(c0) VALUES(2);
```

step2: execute the following transaction statements
```sql
/* t1 */ BEGIN;
/* t1 */ UPDATE t0 SET c0=-1 WHERE false;
/* t2 */ BEGIN;
/* t2 */ INSERT INTO t0(c0) VALUES(4);
/* t1 */ UPDATE t0 SET c0=3 WHERE c0=4; [expcted: blocked , actual: unblocked]
Query OK, 0 rows affected
Rows matched: 0 Changed: 0
/* t2 */ COMMIT;
/* t1 */ COMMIT;
```

step3: query the final dbms state:
check the final state:
```sql
mysql> select * from t0;
+----+
| c0 |
+----+
| 1 |
| 2 |
| 4 |
+----+
```

### 2. What did you expect to see? (Required)
I expected Transaction 1's second statement:
```sql
UPDATE t0 SET c0 = 3 WHERE c0 = 4;
```
to wait for Transaction 2's uncommitted inserted row:
```sql
INSERT INTO t0(c0) VALUES(4);
```
After Transaction 2 commits, Transaction 1 should continue and update the newly committed row from 4 to 3.
Expected final result:
```text
+----+
| c0 |
+----+
| 1 |
| 2 |
| 3 |
+----+
```
This expectation comes from MySQL/InnoDB behavior. In MySQL/InnoDB, even when c0 has no user-defined index, InnoDB scans the hidden clustered index and may encounter the uncommitted inserted record, causing the UPDATE to wait for the record lock.

### 3. What did you see instead (Required)
In TiDB, when c0 has no index:
```sql
CREATE TABLE t0(c0 INT);
```
Transaction 1's second UPDATE does not wait for Transaction 2's uncommitted insert. It returns immediately with:
```text
Query OK, 0 rows affected
Rows matched: 0 Changed: 0
```
Then Transaction 2 commits successfully, and the final table becomes:
```text
+----+
| c0 |
+----+
| 1 |
| 2 |
| 4 |
+----+
```
### 4. What is your TiDB version? (Required)
```sql
mysql> select version();
+--------------------+
| version() |
+--------------------+
| 5.7.25-TiDB-v7.1.2 |
+--------------------+
```

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.