Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Fixed
-
10.5.12
-
OS: Ubuntu-20.04
Description
Isolation Level: Read Uncommitted & Read Committed.
The behaviors of UPDATE for different rows are inconsistent. Just some of the rows are not updated while others are.
/* init */ drop table if exists t; |
/* init */ create table t(a int, b int); |
/* init */ insert into t values(null, 1), (2, 2), (null, null), (null, 3), (4, null); |
|
/* s1 */ begin; |
/* s1 */ update t set a = 10 where 1; |
/* s2 */ begin; |
/* s2 */ update t set b = 20 where a; -- blocked |
/* s1 */ commit; -- s2 unblocked |
/* s2 */ commit; |
|
select * from t; |
|
+------+------+ |
| a | b |
|
+------+------+ |
| 10 | 1 |
|
| 10 | 20 |
|
| 10 | 20 |
|
| 10 | 20 |
|
| 10 | 20 |
|
+------+------+ |
The field b of the first row is not updated but other rows are updated.
After several attempts, I found that the results depend on the distribution of the data in the table rather than the timing.
If the initial table is like:
+------+------+ |
| a | b |
|
+------+------+ |
| 1 | 1 |
|
| 2 | 2 |
|
| null | null | |
| null | 3 | |
| 4 | null | |
+------+------+ |
then, the result will be
+------+------+ |
| a | b |
|
+------+------+ |
| 10 | 20 |
|
| 10 | 20 |
|
| 10 | 20 |
|
| 10 | 20 |
|
| 10 | 20 |
|
+------+------+ |
More specifically, if there exists a row whose column `a` is not NULL, and it is the first record from top to bottom whose column `a` is not NULL. Then, all rows before it with a NULL column `a` will not be updated, while all rows after it with a NULL column `a` will be updated. This means that even the execution of a single statement is not atomic.
This bug can be reproduced under Read Uncommitted and Read Committed.
Attachments
Issue Links
- blocks
-
MDEV-33802 Weird read view after ROLLBACK of other transactions.
-
- Closed
-
- relates to
-
MDEV-26642 Weird SELECT view when a record is modified to the same value by two transactions
-
- Closed
-
-
MDEV-32898 Phantom rows caused by UPDATE of PRIMARY KEY
-
- Closed
-
-
MDEV-35124 Set innodb_snapshot_isolation=ON by default
-
- Closed
-
-
MDEV-26671 Inconsistent SELECT View when modify a record added by another transaction
-
- Closed
-
-
MDEV-34108 Inappropriate semi-consistent read in RC if innodb_snapshot_isolation=ON
-
- Closed
-
-
MDEV-35140 Support innodb-snapshot-isolation in Galera cluster
-
- Stalled
-
I think that this must be addressed in our documentation.
Years ago, the semi-consistent read was originally implemented by me to fix MySQL Bug #3300. The function ha_innobase::try_semi_consistent_read() will enable the semi-consistent reads for the READ COMMITTED and READ UNCOMMITTED isolation levels. Normal consistent reads will wait for a lock on any uncommitted record version.
In the scenario given by the Description, when the second UPDATE statement visits the first row, it will be locked by the first UPDATE, which was not committed yet. For the semi-consistent read, the latest committed version (a,b)=(null,1) will be constructed, and a=null will not satisfy the condition WHERE a. Hence, the row will not be updated.
dinary, are you able to access MySQL Bug #104833, or did you receive any updates for it? It has been made private.