1
0
mirror of https://github.com/MariaDB/server.git synced 2025-11-22 17:44:29 +03:00
Files
mariadb/mysql-test/t/innodb_release_row_locks_early.test
unknown d4fa9ef0c7 MWL#163: release of row locks in InnoDB during prepare
Port the Facebook patch for releasing InnoDB row locks early to the
MWL#116 framework.

A new --innodb-release-locks-early option (off by default) enables a
prepare_ordered() handlerton method which will release row locks and
commit a transaction to memory immediately after successful prepare.

If the server subsequently tries to rollback (ie. due to binlog error),
crashes the server to prevent corrupting the InnoDB state.

mysql-test/r/innodb_release_row_locks_early.result:
  Test case.
mysql-test/t/innodb_release_row_locks_early-master.opt:
  Test case.
mysql-test/t/innodb_release_row_locks_early.test:
  Test case.
sql/log.cc:
  Add DEBUG_SYNC points for testing.
storage/xtradb/handler/ha_innodb.cc:
  Release locks during prepare phase if --innodb-release-locks-early.
  Crash the server if we are asked to rollback after releasing locks and
  committing the transaction to memory.
storage/xtradb/include/srv0srv.h:
  Add variable for --innodb-release-locks-early option.
storage/xtradb/include/trx0sys.ic:
  If --innodb-release-locks-early, treat a transaction as committed to memory
  as soon as it enters the TRX_PREPARED state.
storage/xtradb/srv/srv0srv.c:
  Add variable for --innodb-release-locks-early option.
2010-11-03 17:07:08 +01:00

136 lines
4.0 KiB
Plaintext

--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
# 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 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_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;
# There is a bug (patch pending) that warnings are not shown automatically
# by the client; just do it manually. When bug fix is merged, remove the
# manual SHOW WARNINGS.
SHOW WARNINGS;
connection c2;
--echo # Connection c2
reap;
--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';