mysql - 防止 INSERT INTO ... SELECT 语句创建自己的新快照
问题描述
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,读取的类型会有所不同:
默认情况下,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 引擎。
解决方案
推荐阅读
- javascript - 以降序对随机生成的 SVG 进行排序
- performance - 哪个提供更好的性能:批处理 API 或 HTTP2
- dts - zephyr中yaml文件有什么用
- angular - 基于 Angular 中的数据的 Kendo Excel 导出格式
- javascript - HTML/CSS 悬停下拉菜单
- javascript - 如何在 React Native 中打开 OAuth 模式时提示用户
- python - 我将如何编写这个用 Python 2 编写的 for 循环,称为字符串插值到 python3 的语法中?
- c - 我的 Linux C 进程如何知道在命令行上打开了多少文件?
- node.js - 如何在 NodeJS 中正确使用回调函数
- java - Spring Boot 端点路径