写在前面
本文主要从执行的sql表现出的现象上来分析’可重复读’这个隔离级别,鉴于底层还没了解透彻,就不涉及原理了。
注意:本次示例为Mysql 5.6.43
初始化SQL
CREATE TABLE `users` (
`id` smallint(6) NOT NULL AUTO_INCREMENT,
`name` varchar(25) DEFAULT NULL,
`age` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
TRUNCATE users;
ALTER table `users` auto_increment=1;
INSERT INTO users(`name`,`age`) VALUES('lyf_16',16);
INSERT INTO users(`name`,`age`) VALUES('xtf_17',17);
SELECT * FROM users;
示例:事务a与事务b都是可重复读隔离级别
PS: 以下示例脚本是在2个会话中执行
#tx-a: 设置当前会话为REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT @GLOBAL.TX_ISOLATION AS 'GLOBAL-tx',@@SESSION.TX_ISOLATION AS '@@SESSION-tx';
#tx-b: 设置当前会话为REPEATABLE READ
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT @GLOBAL.TX_ISOLATION AS 'GLOBAL-tx',@@SESSION.TX_ISOLATION AS '@@SESSION-tx';
#tx-a: start
START TRANSACTION;
#tx-b: start
START TRANSACTION;
#以上事务谁先开始都没关系,不影响整体结果。重点在初始读开始于什么时候。
#tx-a: a1 :初始读
SELECT * FROM users;
-- 1 lyf_16 16
-- 2 xtf_17 17
#tx-b: b2
INSERT INTO users(name,age) VALUES('zbz',18);
UPDATE users SET age=99 WHERE id=1;
DELETE FROM users WHERE id=2;
SELECT * FROM users;
-- 1 lyf_16 99
-- 3 zbz 18
#tx-a: a2 :tx-b事务未提交,tx-a未做任务增、删、改前的重复读,结果同a1
SELECT * FROM users;
#tx-b: b3
commit;
#tx-a: a3 :tx-b事务已提交,tx-a未做任务增、删、改前的重复读,结果同a1
SELECT * FROM users;
#tx-a: a4 :更新存在的数据(id=1),更新成功。但是age变成了最新提交的值(tx-b)。tx-a未变更的记录同a1
#这里读取的第一条记录包含了tb更新的99,与a1,a2,a3的读不一致了,即出现幻读
UPDATE users SET `name`='lyf_update' WHERE id=1;
SELECT * FROM users;
-- 1 lyf_update 99
-- 2 xtf_17 17
#tx-a: a5 :更新被其他事务(tx-b)删除了的数据,更新失败。查询结果同a4
UPDATE users SET age=88 WHERE id=2;
SELECT * FROM users;
#tx-a: a6:更新到其他事务(tx-b)新插入的数据,查询结果与a4不同;出现了初始读之后,非本事务(tx-a)插入的数据,即出现幻读
UPDATE users SET age=88 WHERE id=3;
SELECT * FROM users;
-- 1 lyf_update 99
-- 2 xtf_17 17
-- 3 zbz 88
#tx-a: a7
COMMIT;
总结如下:
-
当前事务自己的变更(增,删,改)如果
成功(影响条数不为0)
,则当前事务的查询是可见的。 -
如果当前事务的
成功(影响条数不为0)
变更涉及到了其他已提交事务修改或者新增的记录,则当前事务此时的查询对这些修改或者新增也是可见的(即出现了幻读,)。
在此给出‘幻读’的解读就是:
幻读:出现非本事务变更的,与事务开始后初始读不一致的结果。
以上例子是在Mysql 5.6.43上执行的。至于5.7,5.8…等版本,需要自己去试验了。欢迎把试验后的结果一起交流。
版权声明:本文为NEO_Rat原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。