Bug #120129 Non-deterministic semi-consistent read behavior: UPDATE randomly blocks on non-matching locked rows in READ UNCOMMITTED.

Submitted: 23 Mar 9:29
Reporter: Nikki Zhang Email Updates:
Status: Open 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

[23 Mar 9:29] Nikki Zhang
Description:
In READ UNCOMMITTED (or READ COMMITTED), InnoDB is documented to use "semi-consistent reads" for UPDATE full table scans. If a row is locked but doesn't match the WHERE clause, it should be skipped.
We have found that this optimization is unreliable and non-deterministic. Even with identical data and execution order, the UPDATE statement sometimes correctly "slides past" the lock and sometimes "hangs" on it. This flakiness suggests a race condition in how InnoDB evaluates row visibility or lock status during the "semi-consistent" check.

How to repeat:
/* init */ CREATE TABLE mtest(
c0 VARCHAR(8) NOT NULL,
c1 VARCHAR(15) NOT NULL,
c2 INT PRIMARY KEY,
c3 INT,
c4 CHAR(15) DEFAULT NULL
);
INSERT INTO mtest(c0, c1, c2) VALUES ("", "TRUE", 57); 
INSERT IGNORE INTO mtest(c4, c1, c0, c2) VALUES ("]3", "O", "", 63);
INSERT INTO mtest(c4, c1, c0, c2) VALUES ("Q਌0C&f", "", "35", 63); 
INSERT INTO mtest(c0, c1, c2) VALUES ("", "-oP8%jo", 17); 
INSERT IGNORE INTO mtest(c3, c4, c0, c1, c2) VALUES (77, "", "", "", 52); 
INSERT INTO mtest(c1, c2, c0) VALUES ("t", 85, "E"); 

/* s2 */SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
/* s2 */ BEGIN;
/* s1 */SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
/* s1 */BEGIN;
/* s1 */ SELECT c4, c0, c1, c2 FROM mtest WHERE "" LIMIT 1 LOCK IN SHARE MODE; -- Returns empty, no row lock.
/* s2 */ SELECT c3, c4, c0 FROM mtest WHERE c0 = 'P' LIMIT 2; -- Reads Row A.
/* s1 */ SELECT c4, c1 FROM mtest WHERE c0 = 'P' LOCK IN SHARE MODE;
-- s1 acquires S-Lock on Row A (c2=25).
/* s2 */ UPDATE mtest SET c4 = 'W', c2 = 71 WHERE c4 = '';
-- [CRITICAL POINT]
-- Optimization Expectation: Row A (c4=' ]p%') does NOT match 'WHERE c4='''.
-- s2 should perform a semi-consistent read, see the non-match, and SKIP Row A without blocking.
-- Observed Inconsistency: s2 BLOCKS here waiting for s1's S-Lock on Row A.
/* s2 */ COMMIT;
/* s1 */ ROLLBACK;

Suggested fix:
We suggest the following for your consideration:
Ensure Deterministic Behavior: UPDATE should consistently skip locks on non-matching rows in RU/RC, regardless of timing or transaction history.
Documentation Update: If this is a known technical limitation, we suggest clarifying in the docs that semi-consistent reads are "best-effort" rather than guaranteed.
Thank you for your time and help!

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.037 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.