Commit 2d259187 authored by Vlad Lesin's avatar Vlad Lesin

MDEV-26206 gap lock is not set if implicit lock exists

If lock type is LOCK_GAP or LOCK_ORDINARY, and the transaction holds
implicit lock for the record, then explicit gap-lock will not be set for
the record, as lock_rec_convert_impl_to_expl() returns true and
lock_rec_convert_impl_to_expl() bypasses lock_rec_lock() call.

The fix converts explicit lock to implicit one if requested lock type is
not LOCK_REC_NOT_GAP.

innodb_information_schema test result is also changed as after the fix
the following statements execution:

SET autocommit=0;
INSERT INTO t1 VALUES (5,10);
SELECT * FROM t1 FOR UPDATE;

leads to additional gap lock requests.
parent d9526ae6
CREATE TABLE t(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t VALUES (10), (30);
connect con1,localhost,root,,;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
INSERT INTO t VALUES (20);
SELECT * FROM t WHERE a BETWEEN 10 AND 30;
a
10
20
30
connection default;
SET session innodb_lock_wait_timeout=1;
INSERT INTO t VALUES (15);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
disconnect con1;
DROP TABLE t;
...@@ -45,7 +45,7 @@ trx_last_foreign_key_error varchar(256) YES NULL ...@@ -45,7 +45,7 @@ trx_last_foreign_key_error varchar(256) YES NULL
trx_is_read_only int(1) NO 0 trx_is_read_only int(1) NO 0
trx_autocommit_non_locking int(1) NO 0 trx_autocommit_non_locking int(1) NO 0
trx_state trx_weight trx_tables_in_use trx_tables_locked trx_rows_locked trx_rows_modified trx_concurrency_tickets trx_isolation_level trx_unique_checks trx_foreign_key_checks trx_state trx_weight trx_tables_in_use trx_tables_locked trx_rows_locked trx_rows_modified trx_concurrency_tickets trx_isolation_level trx_unique_checks trx_foreign_key_checks
RUNNING 3 0 1 5 1 0 REPEATABLE READ 1 1 RUNNING 3 0 1 6 1 0 REPEATABLE READ 1 1
trx_isolation_level trx_unique_checks trx_foreign_key_checks trx_isolation_level trx_unique_checks trx_foreign_key_checks
SERIALIZABLE 0 0 SERIALIZABLE 0 0
trx_state trx_isolation_level trx_last_foreign_key_error trx_state trx_isolation_level trx_last_foreign_key_error
......
--source include/have_innodb.inc
--source include/count_sessions.inc
CREATE TABLE t(a INT UNSIGNED PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t VALUES (10), (30);
--connect (con1,localhost,root,,)
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN;
INSERT INTO t VALUES (20);
SELECT * FROM t WHERE a BETWEEN 10 AND 30;
--connection default
SET session innodb_lock_wait_timeout=1;
--error ER_LOCK_WAIT_TIMEOUT
INSERT INTO t VALUES (15);
--disconnect con1
DROP TABLE t;
--source include/wait_until_count_sessions.inc
...@@ -5802,7 +5802,8 @@ lock_sec_rec_read_check_and_lock( ...@@ -5802,7 +5802,8 @@ lock_sec_rec_read_check_and_lock(
if (!page_rec_is_supremum(rec) if (!page_rec_is_supremum(rec)
&& page_get_max_trx_id(block->frame) >= trx_sys.get_min_trx_id() && page_get_max_trx_id(block->frame) >= trx_sys.get_min_trx_id()
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec, && lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
index, offsets)) { index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */ /* We already hold an implicit exclusive lock. */
return DB_SUCCESS; return DB_SUCCESS;
} }
...@@ -5884,7 +5885,8 @@ lock_clust_rec_read_check_and_lock( ...@@ -5884,7 +5885,8 @@ lock_clust_rec_read_check_and_lock(
if (heap_no != PAGE_HEAP_NO_SUPREMUM if (heap_no != PAGE_HEAP_NO_SUPREMUM
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec, && lock_rec_convert_impl_to_expl(thr_get_trx(thr), block, rec,
index, offsets)) { index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */ /* We already hold an implicit exclusive lock. */
return DB_SUCCESS; return DB_SUCCESS;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment