Skip to content

Commit

Permalink
[Issue#6]Lock-sys optimization (#49)
Browse files Browse the repository at this point in the history
* Lock-sys optimization: sharded lock_sys mutex

* Repair Lock-sys releated MTR

* Use AArch64 word_add_fetch in rw_lock_lock_word_incr

* FIX ASSERTION FAILURE: LOCK0LATCHES.CC:42:LOCK_SYS->REC_HASH->N_CELLS == LOCK_SYS->P

* Issue#37 Add copyright and disclaimer information

Co-authored-by: Winston-leon <[email protected]>
  • Loading branch information
zwang28 and Winston-leon authored Apr 13, 2021
1 parent 7d10c82 commit bab0019
Show file tree
Hide file tree
Showing 68 changed files with 3,336 additions and 1,570 deletions.
38 changes: 38 additions & 0 deletions mysql-test/suite/innodb/r/cats-autoinc.result
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,41 @@ SET @@global.innodb_lock_wait_timeout = @innodb_lock_wait_timeout_saved;
# End of Bug #27944920 #
# #
########################
CREATE TABLE t1 (
id INT PRIMARY KEY AUTO_INCREMENT,
val INT
) Engine=InnoDB;
CREATE TABLE t2 (
id INT PRIMARY KEY
) Engine=InnoDB;
CREATE TABLE t3 (
id INT PRIMARY KEY,
val INT
) Engine=InnoDB;
INSERT INTO t1 (id, val) VALUES (1,1);
INSERT INTO t2 (id) VALUES (1),(2),(3);
INSERT INTO t3 (id, val) VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6);
SET @innodb_lock_wait_timeout_saved = @@global.innodb_lock_wait_timeout;
SET @@global.innodb_lock_wait_timeout = 100000;
BEGIN;
SELECT * FROM t2 WHERE id=2 FOR UPDATE;
id
2
BEGIN;
SELECT * FROM t2 WHERE id=3 FOR UPDATE;
id
3
BEGIN;
UPDATE t3 SET val = 13;
SET DEBUG_SYNC = 'lock_wait_will_wait SIGNAL C2_will_wait';
INSERT INTO t1 (val) SELECT id FROM t2;
SET DEBUG_SYNC = 'now WAIT_FOR C2_will_wait';
SET DEBUG_SYNC = 'lock_wait_will_wait SIGNAL C3_will_wait';
INSERT INTO t1 (val) VALUES (13);;
SET DEBUG_SYNC = 'now WAIT_FOR C3_will_wait';
ROLLBACK;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
ROLLBACK;
ROLLBACK;
DROP TABLES t1,t2,t3;
SET @@global.innodb_lock_wait_timeout = @innodb_lock_wait_timeout_saved;
22 changes: 22 additions & 0 deletions mysql-test/suite/innodb/r/lock_rec_unlock.result
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,25 @@ SET DEBUG_SYNC = 'RESET';
# End of Bug #27898384 #
# #
########################
# Bug #31046834 ASSERTION FAILURE: TRX0TRX.CC:2663:TRX_ALLOWED_TWO_LATCHES THREAD 14024410520550
# Bug #31047326 ASSERTION FAILURE: TRX0TRX.CC:2663:TRX_ALLOWED_2_LATCHES THREAD 139840853837568
CREATE TABLE t1 (
id INT PRIMARY KEY,
val INT
) Engine=InnoDB;
INSERT INTO t1 (id, val) VALUES (1,1);
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
SET DEBUG_SYNC = 'after_lock_clust_rec_read_check_and_lock SIGNAL con1_created_lock WAIT_FOR con2_will_wait';
SELECT * FROM t1 WHERE val=13 FOR UPDATE;
SET DEBUG_SYNC = 'now WAIT_FOR con1_created_lock';
BEGIN;
SET DEBUG_SYNC = 'lock_wait_will_wait SIGNAL con2_will_wait';
SELECT * FROM t1 WHERE id=1 FOR UPDATE;
id val
COMMIT;
id val
1 1
COMMIT;
DROP TABLE t1;
SET DEBUG_SYNC = 'RESET';
31 changes: 31 additions & 0 deletions mysql-test/suite/innodb/r/lock_sys_resize.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Bug #31329634 ASSERTION FAILURE:
# LOCK0LATCHES.CC:42:LOCK_SYS->REC_HASH->N_CELLS == LOCK_SYS->P
SELECT @@innodb_buffer_pool_size;
@@innodb_buffer_pool_size
17825792
SELECT @@innodb_buffer_pool_chunk_size;
@@innodb_buffer_pool_chunk_size
1048576
CREATE TABLE t1 (id INT PRIMARY KEY, val VARCHAR(1000)) ENGINE=INNODB;
INSERT INTO t1 (id,val) VALUES (1,''),(2,''),(3,''),(4,''),(5,'');
SET DEBUG_SYNC='lock_rec_restore_from_page_infimum_will_latch
SIGNAL con1_will_latch
WAIT_FOR con1_can_go';
UPDATE t1 SET val='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
SET DEBUG_SYNC='now WAIT_FOR con1_will_latch';
SET GLOBAL DEBUG='+d,syncpoint_after_lock_sys_resize_rec_hash';
SET GLOBAL innodb_buffer_pool_size=
@@innodb_buffer_pool_size * 2 + @@innodb_buffer_pool_chunk_size;
SET DEBUG_SYNC='now WAIT_FOR reached_after_lock_sys_resize_rec_hash';
SET DEBUG_SYNC='now SIGNAL con1_can_go';
SET GLOBAL DEBUG='-d,syncpoint_after_lock_sys_resize_rec_hash';
SET DEBUG_SYNC='now SIGNAL continue_after_lock_sys_resize_rec_hash';
DROP TABLE t1;
SELECT @@innodb_buffer_pool_size;
@@innodb_buffer_pool_size
36700160
SET GLOBAL innodb_buffer_pool_size=
(@@innodb_buffer_pool_size - @@innodb_buffer_pool_chunk_size) div 2;
SELECT @@innodb_buffer_pool_size;
@@innodb_buffer_pool_size
17825792
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
CREATE TABLE t0 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t1 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t3 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t4 (id INT PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t5 (id INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t0 (id) VALUES (1);
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
XA START 'x';
INSERT INTO t1 (id) VALUES (1);;
INSERT INTO t2 (id) VALUES (1);;
INSERT INTO t3 (id) VALUES (1);;
INSERT INTO t4 (id) VALUES (1);;
INSERT INTO t5 (id) VALUES (1);;
SELECT * FROM t0 WHERE id=1 FOR UPDATE;
id
1
XA END 'x';
SET DEBUG_SYNC='lock_trx_release_read_locks_in_x_mode_will_release
SIGNAL c0_releases_in_xmode';
SET DEBUG_SYNC='try_relatch_trx_and_shard_and_do_noted_expected_version
SIGNAL c0_noted_expected_version
WAIT_FOR c0_can_go
EXECUTE 5';
XA PREPARE 'x';
BEGIN;
SET DEBUG_SYNC = 'now WAIT_FOR c0_noted_expected_version';
SET DEBUG_SYNC='lock_wait_will_wait SIGNAL c0_can_go';
SELECT * FROM t1 FOR SHARE;
BEGIN;
SET DEBUG_SYNC = 'now WAIT_FOR c0_noted_expected_version';
SET DEBUG_SYNC='lock_wait_will_wait SIGNAL c0_can_go';
SELECT * FROM t2 FOR SHARE;
BEGIN;
SET DEBUG_SYNC = 'now WAIT_FOR c0_noted_expected_version';
SET DEBUG_SYNC='lock_wait_will_wait SIGNAL c0_can_go';
SELECT * FROM t3 FOR SHARE;
BEGIN;
SET DEBUG_SYNC = 'now WAIT_FOR c0_noted_expected_version';
SET DEBUG_SYNC='lock_wait_will_wait SIGNAL c0_can_go';
SELECT * FROM t4 FOR SHARE;
BEGIN;
SET DEBUG_SYNC = 'now WAIT_FOR c0_noted_expected_version';
SET DEBUG_SYNC='lock_wait_will_wait SIGNAL c0_can_go';
SELECT * FROM t5 FOR SHARE;
SET DEBUG_SYNC='now WAIT_FOR c0_releases_in_xmode';
XA COMMIT 'x';
id
1
COMMIT;
id
1
COMMIT;
id
1
COMMIT;
id
1
COMMIT;
id
1
COMMIT;
DROP TABLE t0;
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;
DROP TABLE t4;
DROP TABLE t5;
20 changes: 20 additions & 0 deletions mysql-test/suite/innodb/r/rec_offsets.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
CREATE TABLE t (
id INT PRIMARY KEY,
c0 INT, c1 INT, c2 INT, c3 INT, c4 INT, c5 INT, c6 INT, c7 INT, c8 INT, c9 INT,
c10 INT, c11 INT, c12 INT, c13 INT, c14 INT, c15 INT, c16 INT, c17 INT, c18 INT, c19 INT,
c20 INT, c21 INT, c22 INT, c23 INT, c24 INT, c25 INT, c26 INT, c27 INT, c28 INT, c29 INT,
c30 INT, c31 INT, c32 INT, c33 INT, c34 INT, c35 INT, c36 INT, c37 INT, c38 INT, c39 INT,
c40 INT, c41 INT, c42 INT, c43 INT, c44 INT, c45 INT, c46 INT, c47 INT, c48 INT, c49 INT,
c50 INT, c51 INT, c52 INT, c53 INT, c54 INT, c55 INT, c56 INT, c57 INT, c58 INT, c59 INT,
c60 INT, c61 INT, c62 INT, c63 INT, c64 INT, c65 INT, c66 INT, c67 INT, c68 INT, c69 INT,
c70 INT, c71 INT, c72 INT, c73 INT, c74 INT, c75 INT, c76 INT, c77 INT, c78 INT, c79 INT,
c80 INT, c81 INT, c82 INT, c83 INT, c84 INT, c85 INT, c86 INT, c87 INT, c88 INT, c89 INT,
c90 INT, c91 INT, c92 INT, c93 INT, c94 INT, c95 INT, c96 INT, c97 INT, c98 INT, c99 INT,
c100 INT UNIQUE KEY
) ENGINE=InnoDB;
BEGIN;
INSERT INTO t (id,c100) VALUES (1,1);
INSERT INTO t (id,c100) VALUES (2,1);
ERROR 23000: Duplicate entry '1' for key 't.c100'
COMMIT;
DROP TABLE t;
94 changes: 94 additions & 0 deletions mysql-test/suite/innodb/t/cats-autoinc.test
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,97 @@
--echo # End of Bug #27944920 #
--echo # #
--echo ########################

# Following scenario is intended to cover the rare case of trx being
# killed while waiting for a table lock, which excersises the table
# lock case in lock_cancel_waiting_and_release function.
#
# To generate a situation when trx is waiting for a table lock inside
# InnoDB we use following scenario:
# C1 locks t2.id = 2
# C3 locks t2.id = 3
# C2 obtains t1.AUTO_INC and waits for C1 t2.id=2 row lock
# C3 tries to insert to t1, and has to wait for C2's autoinc lock
# C1 rolls back, which unlocks t2.id=2, and C2 proceeds to lock t2.id=3,
# and now is blocked by C3, but C3 is already blocked by C2, so we have
# a deadlock cycle.
# We make C2 heavy to make sure that C3 is chosen as victim, by modyfing
# many rows in t3.

CREATE TABLE t1 (
id INT PRIMARY KEY AUTO_INCREMENT,
val INT
) Engine=InnoDB;

CREATE TABLE t2 (
id INT PRIMARY KEY
) Engine=InnoDB;

CREATE TABLE t3 (
id INT PRIMARY KEY,
val INT
) Engine=InnoDB;

INSERT INTO t1 (id, val) VALUES (1,1);
INSERT INTO t2 (id) VALUES (1),(2),(3);
INSERT INTO t3 (id, val) VALUES (1,1),(2,2),(3,3),(4,4),(5,5),(6,6);

# Save the original settings, to be restored at the end of test
SET @innodb_lock_wait_timeout_saved = @@global.innodb_lock_wait_timeout;

# Make sure that transactions will not finish prematurely
SET @@global.innodb_lock_wait_timeout = 100000;


--connect (C1, localhost, root,,)
--connect (C2, localhost, root,,)
--connect (C3, localhost, root,,)

--connection C1
BEGIN;
SELECT * FROM t2 WHERE id=2 FOR UPDATE;

--connection C3
BEGIN;
SELECT * FROM t2 WHERE id=3 FOR UPDATE;

--connection C2
BEGIN;
UPDATE t3 SET val = 13;
SET DEBUG_SYNC = 'lock_wait_will_wait SIGNAL C2_will_wait';
--send INSERT INTO t1 (val) SELECT id FROM t2
# C2 --waits-for[t2.id=2]--> C1

--connection C3
SET DEBUG_SYNC = 'now WAIT_FOR C2_will_wait';
SET DEBUG_SYNC = 'lock_wait_will_wait SIGNAL C3_will_wait';
--send INSERT INTO t1 (val) VALUES (13);
# C3 --waits-for[t1.autoinc]--> C2 --waits-for[t2.id=2]--> C1

--connection C1
SET DEBUG_SYNC = 'now WAIT_FOR C3_will_wait';
ROLLBACK;
# C3 --waits-for[t1.autoinc]--> C2 --waits-for[t2.id=3]--> C3
# this is a deadlock.

--connection C3
--error ER_LOCK_DEADLOCK
--reap
ROLLBACK;

--connection C2
--reap
ROLLBACK;

--connection default
--disconnect C1
--disconnect C2
--disconnect C3


DROP TABLES t1,t2,t3;

# Restore saved state

SET @@global.innodb_lock_wait_timeout = @innodb_lock_wait_timeout_saved;

45 changes: 45 additions & 0 deletions mysql-test/suite/innodb/t/lock_rec_unlock.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
--source include/have_debug_sync.inc
--source include/count_sessions.inc

--echo #################################################################
--echo # #
Expand Down Expand Up @@ -139,3 +140,47 @@
--echo # End of Bug #27898384 #
--echo # #
--echo ########################


--echo # Bug #31046834 ASSERTION FAILURE: TRX0TRX.CC:2663:TRX_ALLOWED_TWO_LATCHES THREAD 14024410520550
--echo # Bug #31047326 ASSERTION FAILURE: TRX0TRX.CC:2663:TRX_ALLOWED_2_LATCHES THREAD 139840853837568

CREATE TABLE t1 (
id INT PRIMARY KEY,
val INT
) Engine=InnoDB;
INSERT INTO t1 (id, val) VALUES (1,1);

--connect (con1, localhost, root,,)
--connect (con2, localhost, root,,)

--connection con1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
SET DEBUG_SYNC = 'after_lock_clust_rec_read_check_and_lock SIGNAL con1_created_lock WAIT_FOR con2_will_wait';
--send SELECT * FROM t1 WHERE val=13 FOR UPDATE

--connection con2
SET DEBUG_SYNC = 'now WAIT_FOR con1_created_lock';
BEGIN;
SET DEBUG_SYNC = 'lock_wait_will_wait SIGNAL con2_will_wait';
--send SELECT * FROM t1 WHERE id=1 FOR UPDATE

--connection con1
--reap
COMMIT;

--connection con2
--reap
COMMIT;



# Clean up:
--connection default
--disconnect con1
--disconnect con2
DROP TABLE t1;
SET DEBUG_SYNC = 'RESET';

--source include/wait_until_count_sessions.inc
2 changes: 2 additions & 0 deletions mysql-test/suite/innodb/t/lock_sys_resize-master.opt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
--innodb_buffer-pool-size=17825792
--innodb-buffer-pool-chunk-size=1048576
Loading

0 comments on commit bab0019

Please sign in to comment.