Bug #118516 Unexpected blocked statement when different select statements are executed
Submitted: 24 Jun 10:42 Modified: 3 Jul 18:35
Reporter: Kaiming Zhang Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S3 (Non-critical)
Version:8.0.39 OS:Any
Assigned to: CPU Architecture:Any
Tags: block

[24 Jun 10:42] Kaiming Zhang
Description:
In our tests, we found that in transaction TX2 under SERIALIZABLE isolation level, adding the statement "SELECT c1, c2 FROM mtest WHERE x = 0;" blocks TX1's UPDATE. We believe this statement should not block TX1's update because the rows it queries are different from the rows TX1 is updating.

How to repeat:
conn_0> CREATE TABLE mtest(x INT DEFAULT 0,c0 INT, c1 INT, c2 INT UNIQUE AUTO_INCREMENT);
conn_0> INSERT IGNORE INTO mtest(c0, c1, c2, x) VALUES (1, 1, 1, 1);
conn_0> INSERT INTO mtest(c0, c1, c2) VALUES (1, 1, NULL);
+---+-----+----+----+
| x |  c0 | c1 | c2 |
+---+-----+----+----+
| 1 |  1  |  1 |  1 |
+---+-----+----+----+
| 0 |  1  |  1 |  2 |
+---+-----+----+----+
---------- Test case 0 ----------
conn_0> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.000 sec)

conn_1> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Query OK, 0 rows affected (0.000 sec)

conn_1> BEGIN;
Query OK, 0 rows affected (0.000 sec)

conn_0> BEGIN;
Query OK, 0 rows affected (0.000 sec)

conn_1> SELECT c1, c2 FROM mtest WHERE c2 = 2 FOR UPDATE;
+------+----+
| c1   | c2 |
+------+----+
|    1 |  2 |
+------+----+
1 row in set (0.001 sec)

conn_0> UPDATE mtest SET c0=2, c1=3 WHERE c2 = 1;
Query OK, 1 row affected (0.001 sec)
Rows matched: 1  Changed: 1  Warnings: 0

conn_0> ROLLBACK;
Query OK, 0 rows affected (0.011 sec)

conn_1> ROLLBACK;
Query OK, 0 rows affected (0.000 sec)

---------- Test case 1 ----------

conn_0> SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Query OK, 0 rows affected (0.000 sec)

conn_1> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Query OK, 0 rows affected (0.000 sec)

conn_1> BEGIN;
Query OK, 0 rows affected (0.000 sec)

conn_0> BEGIN;
Query OK, 0 rows affected (0.000 sec)

conn_0> SELECT c1, c2 FROM mtest WHERE c2 = 2 FOR UPDATE;
+------+----+
| c1   | c2 |
+------+----+
|    1 |  2 |
+------+----+
1 row in set (0.001 sec)

conn_0> SELECT c1, c2 FROM mtest WHERE x = 0;
+------+----+
| c1   | c2 |
+------+----+
|    1 |  2 |
+------+----+
1 row in set (0.000 sec)

MySQL [test]> UPDATE mtest SET c0=2, c1=3 WHERE c2 = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
**Unexpected blocked statement**

Suggested fix:
The statement "SELECT c1, c2 FROM mtest WHERE x = 0;" should only acquire a shared lock on the row(s) where x=0.
[1 Jul 14:13] MySQL Verification Team
I can reproduce this behavior but I do not believe this is a bug.