隔离级别之可重复读级别解读

  • Post author:
  • Post category:其他




写在前面

本文主要从执行的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;



总结如下:

  1. 当前事务自己的变更(增,删,改)如果

    成功(影响条数不为0)

    ,则当前事务的查询是可见的。

  2. 如果当前事务的

    成功(影响条数不为0)

    变更涉及到了其他已提交事务修改或者新增的记录,则当前事务此时的查询对这些修改或者新增也是可见的(即出现了幻读,)。

在此给出‘幻读’的解读就是:


幻读:出现非本事务变更的,与事务开始后初始读不一致的结果。

以上例子是在Mysql 5.6.43上执行的。至于5.7,5.8…等版本,需要自己去试验了。欢迎把试验后的结果一起交流。



版权声明:本文为NEO_Rat原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。