From f053874a96a45836922399b68dfe76a91e5793ce Mon Sep 17 00:00:00 2001 From: Daniel Black Date: Fri, 24 Apr 2026 11:38:04 +1000 Subject: [PATCH] MDEV-38817: innodb.skip_locked_nowait fails: SELECT NOWAIT gets ER_LOCK_WAIT_TIMEOUT MDEV-38019 added an optimization in select_send::send_eof() that sends the OK packet to the client before the server finishes cleanup, allowing the client to process results sooner. The guard !thd->transaction->stmt.is_trx_read_write() was intended to exclude write transactions, but mark_trx_read_write() is only called for DML (INSERT/UPDATE/DELETE), not for locking reads. This caused SELECT ... FOR UPDATE with autocommit to send OK before external_lock(F_UNLCK) committed and released locks, creating a race where another connection using NOWAIT could see still-held locks and immediately fail with ER_LOCK_WAIT_TIMEOUT. We fix this in the case case by inserting --ping, that ensures the cleanup on the same server thread occurs completing the external_lock(F_UNLCK). Thanks Arcadiy Ivanov for the analysis that formed the majority of this commit message. --- mysql-test/suite/innodb/t/skip_locked_nowait.test | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mysql-test/suite/innodb/t/skip_locked_nowait.test b/mysql-test/suite/innodb/t/skip_locked_nowait.test index b12999c6f4479..0e8edaa7b2abb 100644 --- a/mysql-test/suite/innodb/t/skip_locked_nowait.test +++ b/mysql-test/suite/innodb/t/skip_locked_nowait.test @@ -179,6 +179,10 @@ connection con1; SET @g = ST_GeomFromText('POLYGON((0 0,0 3,3 3,0 3,0 0))'); SELECT seat_id, state, ST_AsText(pos) FROM t1 FORCE INDEX (pos) WHERE state = 0 AND MBRWithin(pos, @g) FOR UPDATE; +# ensure the state cleanup that performs external_lock(F_UNLCK) +# so the next default connection can obtain the lock without +# a timeout +--ping connection default; BEGIN;