mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-36330: SERIALIZABLE read inconsistency
At TRANSACTION ISOLATION LEVEL SERIALIZABLE, InnoDB would fail to flag a write/read conflict, which would be a violation already at the more relaxed REPEATABLE READ level when innodb_snapshot_isolation=ON. Fix: Create a read view and start the transaction at the same time. Thus, lock checks will be able to consult the correct read view to flag ER_CHECKREAD if we are about to lock a record that was committed after the start of our transaction. innobase_start_trx_and_assign_read_view(): At any other isolation level than READ UNCOMMITTED, do create a read view. This is needed for the correct operation of START TRANSACTION WITH CONSISTENT SNAPSHOT. ha_innobase::store_lock(): At SERIALIZABLE isolation level, if the transaction was not started yet, start it and open a read view. An alternative way to achieve this would be to make trans_begin() treat START TRANSACTION (or BEGIN) in the same way as START TRANSACTION WITH CONSISTENT SNAPSHOT when the isolation level is SERIALIZABLE. innodb_isolation_level(const THD*): A simpler version of innobase_map_isolation_level(). Compared to earlier, we will return READ UNCOMMITTED also if the :newraw option is set for the InnoDB system tablespace. Reviewed by: Vladislav Lesin
This commit is contained in:
@@ -166,7 +166,6 @@ SELECT * FROM t FORCE INDEX (b) FOR UPDATE;
|
||||
a b
|
||||
1 NULL
|
||||
COMMIT;
|
||||
disconnect con_weird;
|
||||
connection consistent;
|
||||
SELECT * FROM t FORCE INDEX (b) FOR UPDATE;
|
||||
a b
|
||||
@@ -230,9 +229,58 @@ UPDATE t SET b=4 WHERE a=1;
|
||||
connection consistent;
|
||||
SELECT * FROM t WHERE a=1 FOR UPDATE;
|
||||
ERROR HY000: Record has changed since last read in table 't'
|
||||
disconnect consistent;
|
||||
disconnect disable_purging;
|
||||
connection default;
|
||||
SET DEBUG_SYNC="RESET";
|
||||
DROP TABLE t;
|
||||
CREATE TABLE t1(a INT) ENGINE=InnoDB STATS_PERSISTENT=0;
|
||||
CREATE TABLE t2(a INT) ENGINE=InnoDB STATS_PERSISTENT=0;
|
||||
BEGIN;
|
||||
INSERT INTO t1 SET a=1;
|
||||
connection con_weird;
|
||||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
BEGIN;
|
||||
INSERT INTO t2 SET a=1;
|
||||
connection consistent;
|
||||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
BEGIN;
|
||||
INSERT INTO t2 SET a=2;
|
||||
connection default;
|
||||
COMMIT;
|
||||
connection con_weird;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
1
|
||||
COMMIT;
|
||||
connection consistent;
|
||||
SELECT * FROM t1;
|
||||
ERROR HY000: Record has changed since last read in table 't1'
|
||||
COMMIT;
|
||||
connection default;
|
||||
BEGIN;
|
||||
INSERT INTO t1 SET a=2;
|
||||
connection con_weird;
|
||||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
INSERT INTO t2 SET a=3;
|
||||
connection consistent;
|
||||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
START TRANSACTION WITH CONSISTENT SNAPSHOT;
|
||||
INSERT INTO t2 SET a=2;
|
||||
connection default;
|
||||
COMMIT;
|
||||
connection con_weird;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
COMMIT;
|
||||
disconnect con_weird;
|
||||
connection consistent;
|
||||
SELECT * FROM t1;
|
||||
ERROR HY000: Record has changed since last read in table 't1'
|
||||
COMMIT;
|
||||
disconnect consistent;
|
||||
connection default;
|
||||
DROP TABLE t1,t2;
|
||||
# End of 10.6 tests
|
||||
|
Reference in New Issue
Block a user