mirror of
https://github.com/MariaDB/server.git
synced 2025-02-10 15:35:34 +01:00
![Marko Mäkelä](/assets/img/avatar_default.png)
Under unknown circumstances, the SQL layer may wrongly disregard an invocation of thd_mark_transaction_to_rollback() when an InnoDB transaction had been aborted (rolled back) due to one of the following errors: * HA_ERR_LOCK_DEADLOCK * HA_ERR_RECORD_CHANGED (if innodb_snapshot_isolation=ON) * HA_ERR_LOCK_WAIT_TIMEOUT (if innodb_rollback_on_timeout=ON) Such an error used to cause a crash of InnoDB during transaction commit. These changes aim to catch and report the error earlier, so that not only this crash can be avoided but also the original root cause be found and fixed more easily later. The idea of this fix is from Michael 'Monty' Widenius. HA_ERR_ROLLBACK: A new error code that will be translated into ER_ROLLBACK_ONLY, signalling that the current transaction has been aborted and the only allowed action is ROLLBACK. trx_t::state: Add TRX_STATE_ABORTED that is like TRX_STATE_NOT_STARTED, but noting that the transaction had been rolled back and aborted. trx_t::is_started(): Replaces trx_is_started(). ha_innobase: Check the transaction state in various places. Simplify the logic around SAVEPOINT. ha_innobase::is_valid_trx(): Replaces ha_innobase::is_read_only(). The InnoDB logic around transaction savepoints, commit, and rollback was unnecessarily complex and might have contributed to this inconsistency. So, we are simplifying that logic as well. trx_savept_t: Replace with const undo_no_t*. When we rollback to a savepoint, all we need to know is the number of undo log records that must survive. trx_named_savept_t, DB_NO_SAVEPOINT: Remove. We can store undo_no_t directly in the space allocated at innobase_hton->savepoint_offset. fts_trx_create(): Do not copy previous savepoints. fts_savepoint_rollback(): If a savepoint was not found, roll back everything after the default savepoint of fts_trx_create(). The test innodb_fts.savepoint is extended to cover this code. Reviewed by: Vladislav Lesin Tested by: Matthias Leich
191 lines
4.5 KiB
Text
191 lines
4.5 KiB
Text
--source include/have_innodb.inc
|
|
|
|
--disable_query_log
|
|
call mtr.add_suppression("InnoDB: Transaction was aborted due to ");
|
|
--enable_query_log
|
|
|
|
--echo #
|
|
--echo # MDEV-26642 Weird SELECT view when a record is
|
|
--echo # modified to the same value by two transactions
|
|
--echo # MDEV-32898 Phantom rows caused by updates of PRIMARY KEY
|
|
--echo #
|
|
|
|
CREATE TABLE t(a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
|
|
INSERT INTO t VALUES (1,1),(2,2);
|
|
BEGIN; SELECT * FROM t LOCK IN SHARE MODE;
|
|
--connect con_weird,localhost,root
|
|
BEGIN;
|
|
SELECT * FROM t;
|
|
--connect consistent,localhost,root
|
|
SET innodb_snapshot_isolation=ON;
|
|
BEGIN;
|
|
SELECT * FROM t;
|
|
--connection default
|
|
UPDATE t SET a=3 WHERE b=2;
|
|
COMMIT;
|
|
--connection consistent
|
|
--error ER_CHECKREAD
|
|
UPDATE t SET b=3;
|
|
SELECT * FROM t;
|
|
COMMIT;
|
|
--connection con_weird
|
|
UPDATE t SET b=3;
|
|
SELECT * FROM t;
|
|
COMMIT;
|
|
--connection default
|
|
SELECT * FROM t;
|
|
DROP TABLE t;
|
|
|
|
--echo #
|
|
--echo # MDEV-26643 Inconsistent behaviors of UPDATE under
|
|
--echo # READ UNCOMMITTED and READ COMMITTED isolation level
|
|
--echo #
|
|
|
|
CREATE TABLE t(a INT, b INT) ENGINE=InnoDB;
|
|
INSERT INTO t VALUES(NULL, 1), (2, 2);
|
|
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
|
BEGIN; UPDATE t SET a = 10;
|
|
|
|
--connection consistent
|
|
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
|
--send UPDATE t SET b = 20 WHERE a
|
|
|
|
--connection default
|
|
let $wait_condition=
|
|
select count(*) = 1 from information_schema.processlist
|
|
where state = 'Updating'
|
|
and info = 'UPDATE t SET b = 20 WHERE a';
|
|
--source include/wait_condition.inc
|
|
|
|
COMMIT;
|
|
|
|
--connection consistent
|
|
--reap
|
|
SELECT * FROM t;
|
|
|
|
--connection default
|
|
TRUNCATE TABLE t;
|
|
INSERT INTO t VALUES(NULL, 1), (2, 2);
|
|
BEGIN; UPDATE t SET a = 10;
|
|
|
|
--connection consistent
|
|
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
|
--send UPDATE t SET b = 20 WHERE a
|
|
|
|
--connection default
|
|
let $wait_condition=
|
|
select count(*) = 1 from information_schema.processlist
|
|
where info = 'UPDATE t SET b = 20 WHERE a';
|
|
--source include/wait_condition.inc
|
|
|
|
COMMIT;
|
|
|
|
--connection consistent
|
|
--reap
|
|
SELECT * FROM t;
|
|
|
|
--connection default
|
|
TRUNCATE TABLE t;
|
|
INSERT INTO t VALUES(NULL, 1), (2, 2);
|
|
BEGIN; UPDATE t SET a = 10;
|
|
|
|
--connection con_weird
|
|
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
|
|
send UPDATE t SET b = 20 WHERE a;
|
|
|
|
--connection default
|
|
let $wait_condition=
|
|
select count(*) = 1 from information_schema.processlist
|
|
where state = 'Updating'
|
|
and info = 'UPDATE t SET b = 20 WHERE a';
|
|
--source include/wait_condition.inc
|
|
|
|
SELECT * FROM t;
|
|
COMMIT;
|
|
|
|
--connection con_weird
|
|
--reap
|
|
COMMIT;
|
|
|
|
--connection default
|
|
SELECT * FROM t;
|
|
TRUNCATE TABLE t;
|
|
|
|
--echo #
|
|
--echo # MDEV-34108 Inappropriate semi-consistent read in snapshot isolation
|
|
--echo #
|
|
INSERT INTO t VALUES(NULL, 1), (1, 1);
|
|
BEGIN;
|
|
UPDATE t SET b = 3;
|
|
|
|
--connection consistent
|
|
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
|
|
BEGIN;
|
|
# As semi-consistent read is disabled for innodb_snapshot_isolation=ON, the
|
|
# following UPDATE must be blocked on the first record.
|
|
--send UPDATE t SET b = 2 WHERE a
|
|
|
|
--connection default
|
|
let $wait_condition=
|
|
select count(*) = 1 from information_schema.processlist
|
|
where state = 'Updating' and info = 'UPDATE t SET b = 2 WHERE a';
|
|
--source include/wait_condition.inc
|
|
|
|
UPDATE t SET a = 1;
|
|
COMMIT;
|
|
--connection consistent
|
|
# If the bug wouldn't be fixed, the result would be (1,3),(1,2), because
|
|
# "UPDATE t SET b = 2 WHERE a" would be blocked on the second (1,3) record,
|
|
# as semi-consistent read would filter out the first (null,3) record without
|
|
# blocking.
|
|
--reap
|
|
COMMIT;
|
|
|
|
--connection default
|
|
SELECT * FROM t;
|
|
DROP TABLE t;
|
|
|
|
--echo #
|
|
--echo # MDEV-33802 Weird read view after ROLLBACK of other transactions
|
|
--echo #
|
|
|
|
CREATE TABLE t(a INT PRIMARY KEY, b INT UNIQUE) ENGINE=InnoDB;
|
|
INSERT INTO t SET a=1;
|
|
|
|
BEGIN; INSERT INTO t SET a=2;
|
|
|
|
--connection consistent
|
|
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
|
SAVEPOINT sp1;
|
|
--disable_ps2_protocol
|
|
--error ER_CHECKREAD
|
|
SELECT * FROM t FORCE INDEX (b) FOR UPDATE;
|
|
--enable_ps2_protocol
|
|
SAVEPOINT sp1;
|
|
|
|
--connection con_weird
|
|
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
|
send
|
|
SELECT * FROM t FORCE INDEX (b) FOR UPDATE;
|
|
|
|
--connection default
|
|
let $wait_condition=
|
|
select count(*) = 1 from information_schema.processlist
|
|
where state = 'Sending data'
|
|
and info LIKE 'SELECT * FROM t %';
|
|
--source include/wait_condition.inc
|
|
ROLLBACK;
|
|
|
|
--connection con_weird
|
|
--reap
|
|
SELECT * FROM t FORCE INDEX (b) FOR UPDATE;
|
|
--disconnect con_weird
|
|
|
|
--connection consistent
|
|
SELECT * FROM t FORCE INDEX (b) FOR UPDATE;
|
|
--disconnect consistent
|
|
|
|
--connection default
|
|
DROP TABLE t;
|
|
|
|
--echo # End of 10.6 tests
|