MySQL / MariaDb InnoDb引擎是否可以执行INSERT INTO ... SELECT
语句并使用由当前REPEATABLE READ
事务创建的快照?
示例(除以下提到的语句外,所有语句均在一个会话中运行)
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION; -- snapshot 1 for this transaction is created
SELECT * FROM t1; -- result is 1 row, snapshot 1 is used
-- another transaction (different session) inserts and commits new row into t1 table
SELECT * FROM t1; -- result is still 1 row, because its REPEATABLE READ, still using snapshot 1
INSERT INTO t2 SELECT * FROM t1; -- this SELECT creates new snapshot 2
SELECT * FROM t2; -- result are 2 rows
SELECT * FROM t1; -- result is still 1 row, using snapshot 1
是否可以使这一行:
INSERT INTO t2 SELECT * FROM t1; -- this SELECT creates new snapshot 2
...使用快照1?以及为什么MySQL这样表现。是不是违反隔离原则?
此行为记录在这里https://dev.mysql.com/doc/refman/8.0/en/innodb-consistent-read.html
对于未指定FOR UPDATE或FOR SHARE的INSERT INTO ... SELECT,UPDATE ...(SELECT)和CREATE TABLE ... SELECT等子句中的selects子句,读取的类型各不相同:
默认情况下,InnoDB使用更强的锁,并且SELECT部分的行为类似于READ COMMITTED,其中即使在同一事务中,每次一致的读取也会设置并读取自己的新快照。
以下是上面使用的一些表格结构:
CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
CREATE TABLE t2 (id INT NOT NULL PRIMARY KEY) ENGINE=InnoDB;
唯一重要的是InnoDB引擎。