Bug #108015 | select under repeatable read isolation level returns stale version of data | ||
---|---|---|---|
Submitted: | 28 Jul 2022 17:02 | Modified: | 29 Jul 2022 12:04 |
Reporter: | Peiyuan Liu | Email Updates: | |
Status: | Duplicate | Impact on me: | |
Category: | MySQL Server | Severity: | S2 (Serious) |
Version: | 8.0.29,8.0.30 | OS: | Linux (Ubuntu/CentOS) |
Assigned to: | CPU Architecture: | x86 | |
Tags: | REPEATABLE-READ TRANSACTION |
[28 Jul 2022 17:02]
Peiyuan Liu
[29 Jul 2022 7:41]
Peiyuan Liu
A more concise case: https://github.com/lpypl/SelectStaleData # Bug Description ## Tested Version - 8.0.29 ## Schema ``` create table if not exists t (k integer, v integer, primary key(k)); delete from t; insert into t(k, v) values (1, 1); ``` ## Operations (From General Log) | Session | Operation | | ------- | ------------------------------------------------------- | | 282 | SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE | | 281 | SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ | | 282 | start transaction | | 282 | update t set v = 2 where k = 1 | | 282 | commit | | 281 | start transaction | | 281 | select k, v from t where v = 88 | | 281 | update t set v = 2 where k = 1 | | 281 | select k, v from t where k = 1 | | 281 | commit | ## How to Repeat - `transformer.py` translates `minimal-general.log` to `minimal-operations.json` - `player.py` create a mysql client process for each session - `player.py` iterates over the list of operations from `minimal-operations.json`, and sends each operation to its session **without waiting for `Query OK`** - `play.sh` is a script that keeps replaying this reproducible case until it succeeds. ## Wrong Query Result ### Description - In the beginning, `v` of `Key<1>` is `1`. ``` +---+------+ | k | v | +---+------+ | 1 | 1 | +---+------+ ``` - Then Session-1001 updates `v` of `Key<1>` to `2`. Note that it successfully changes that value, because the query result is: ``` Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 ``` - When Session-1002 trys updating `v` of `Key<1>` to `2`. It fails to change that value because the vlaue is already `2`: ``` Query OK, 0 rows affected (0.00 sec) Rows matched: 1 Changed: 0 Warnings: 0 ``` - Thers is no wrong execution results so far. - Next, Session-1002 executes ``` select k, v from t where k = 1 ``` As we known, latest `v` of `Key<1>` is `2` However, the query result is: ``` +---+------+ | k | v | +---+------+ | 1 | 1 | +---+------+ 1 row in set (0.01 sec) ``` The database returns a stale version of data for `Key<1>` ### Details #### Initial Data ``` +---+------+ | k | v | +---+------+ | 1 | 1 | +---+------+ ``` #### Execution Result of Session-1001 ``` -------------- SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE -------------- Query OK, 0 rows affected (0.00 sec) -------------- start transaction -------------- Query OK, 0 rows affected (0.00 sec) -------------- update t set v = 2 where k = 1 -------------- Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 -------------- commit -------------- Query OK, 0 rows affected (0.00 sec) Bye ``` #### Execution Result of Session-1002 ``` -------------- SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ -------------- Query OK, 0 rows affected (0.00 sec) -------------- start transaction -------------- Query OK, 0 rows affected (0.00 sec) -------------- select k, v from t where v = 88 -------------- Empty set (0.00 sec) -------------- update t set v = 2 where k = 1 -------------- Query OK, 0 rows affected (0.00 sec) Rows matched: 1 Changed: 0 Warnings: 0 -------------- select k, v from t where k = 1 -------------- +---+------+ | k | v | +---+------+ | 1 | 1 | +---+------+ 1 row in set (0.01 sec) -------------- commit -------------- Query OK, 0 rows affected (0.00 sec) Bye ``` ## Key Points to repeat this Bug ### Request Rate is Critical - Sleep for 0~0.003 seconds between two operations is OK for reproducing this bug - If the sleep is longer, it tends to produce correct execution results ### Update to the same value - Two sessions update `v` to the same value - And the update of Session-1002 must match but not change ### Isolation Level - Isolation Level of Session-1001 doesn't matter, RU/RC/RR/SR all is OK - According to our tests, Isolation Level of Session-1002 must be RR ### For Session-1002, the extra select before the update for `Key<1>` seems unnecessary. But it greatly improves the chance of repeat ``` select k, v from t where v = 88 ```
[29 Jul 2022 7:51]
Peiyuan Liu
It can also be repeated on mysql 8.0.30
[29 Jul 2022 12:04]
MySQL Verification Team
Hi Mr. No, Thank you for your bug report. However, your report is a duplicate of the following bug: https://bugs.mysql.com/bug.php?id=100328 You can follow its progress by subscribing to it. That bug is still unresolved, hence it will also be present in 8.0.31.