mariadb/mysql-test/t/innodb_release_row_locks_early.test

137 lines
3.9 KiB
Text
Raw Normal View History

--source include/have_debug_sync.inc
--source include/have_innodb.inc
--source include/have_log_bin.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (k INT NOT NULL, a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, PRIMARY KEY(k)) ENGINE=InnoDB;
INSERT INTO t1 (k, a, b, c) VALUES (1, 0, 0, 0);
INSERT INTO t1 (k, a, b, c) VALUES (2, 0, 0, 0);
INSERT INTO t1 (k, a, b, c) VALUES (3, 0, 0, 0);
INSERT INTO t1 (k, a, b, c) VALUES (4, 0, 0, 0);
RESET MASTER;
SET DEBUG_SYNC= 'RESET';
# Two transactions A,B that update the same row.
# A releases row locks during the prepare phase, and waits using DEBUG_SYNC.
# B then updates the same row.
# Verify that
# - B's update can proceed while A is waiting for commit, showing that
# locks are released early.
# - B cannot be binlogged before A.
connect(c1,127.0.0.1,root,,test,$MASTER_MYPORT,);
connect(c2,127.0.0.1,root,,test,$MASTER_MYPORT,);
connection c1;
--echo # Connection c1
# Fix binlog format (otherwise SHOW BINLOG EVENTS will fluctuate).
SET binlog_format= mixed;
# First verify that row locks are released early.
BEGIN;
UPDATE t1 SET a=10 WHERE k=1;
# Wait until c2 starts COMMIT, to verify that we release our locks in prepare.
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committing";
send COMMIT;
connection c2;
--echo # Connection c2
SET binlog_format= mixed;
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
BEGIN;
SELECT * FROM t1 WHERE k=1 FOR UPDATE;
UPDATE t1 SET a=20 WHERE k=1;
SET DEBUG_SYNC="now SIGNAL c2_committing";
COMMIT;
connection c1;
--echo # Connection c1
reap;
# Now verify that binlog order is correct.
BEGIN;
UPDATE t1 SET a=10 WHERE k=2;
# This time wait until c2 is binlogged. This should time out, as we must not
# allow c2 to finish commit before c1.
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committed TIMEOUT 2";
send COMMIT;
connection c2;
--echo # Connection c2
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
BEGIN;
SELECT * FROM t1 WHERE k=2 FOR UPDATE;
UPDATE t1 SET a=20 WHERE k=2;
SET DEBUG_SYNC="binlog_after_log_and_order SIGNAL c2_committed";
send COMMIT;
connection c1;
--echo # Connection c1
--echo # This should warn about DEBUG_SYNC timeout
reap;
connection c2;
--echo # Connection c2
reap;
--replace_column 2 # 5 #
--replace_regex /xid=[0-9]+/xid=XX/
SHOW BINLOG EVENTS LIMIT 2,12;
connection c1;
--echo # Connection c1
# Now the same thing, but using autocommit.
RESET MASTER;
# First verify that row locks are released early.
# Wait until c2 starts COMMIT, to verify that we release our locks in prepare.
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committing";
send UPDATE t1 SET a=10 WHERE k=3;
connection c2;
--echo # Connection c2
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
SELECT * FROM t1 WHERE k=3 FOR UPDATE;
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c2_committing";
UPDATE t1 SET a=20 WHERE k=3;
connection c1;
--echo # Connection c1
reap;
# Now verify that binlog order is correct, this time with autocommit.
# This time wait until c2 is binlogged. This should time out, as we must not
# allow c2 to finish commit before c1.
SET DEBUG_SYNC="commit_after_release_LOCK_prepare_ordered SIGNAL c1_prepared WAIT_FOR c2_committed TIMEOUT 2";
send UPDATE t1 SET a=10 WHERE k=4;
connection c2;
--echo # Connection c2
SET DEBUG_SYNC="now WAIT_FOR c1_prepared";
SELECT * FROM t1 WHERE k=4 FOR UPDATE;
SET DEBUG_SYNC="binlog_after_log_and_order SIGNAL c2_committed";
send UPDATE t1 SET a=20 WHERE k=4;
connection c1;
--echo # Connection c1
--echo # This should warn about DEBUG_SYNC timeout
reap;
connection c2;
--echo # Connection c2
reap;
--replace_column 2 # 5 #
--replace_regex /xid=[0-9]+/xid=XX/
SHOW BINLOG EVENTS LIMIT 1,12;
SELECT * FROM t1 ORDER BY k;
DROP TABLE t1;
SET DEBUG_SYNC= 'RESET';