mysql版本是8.0
文章目录
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED | YES | YES | YES |
READ COMMITTED | NO | YES | YES |
REPEATABLE READ | NO | NO | YES |
SERIALIZABLE | NO | NO | NO |
- 脏读:事务的修改,即使没有提交,对其他事务也是可见的。即事务可以读取未提交的数据。
- 不可重复读:一个事务开始时,只能看见自己已经提交的事务所做的修改。两次同样的查询,会得到不一样的结果。
- 幻读:当A事务读取某个范围内的记录时,事务B又在该范围内插入了新的记录,A事务再次读取该范围的记录时,会产生幻行。
准备工作
-
查看当前的隔离级别:
show variable like '%transaction_isolation%'
-
设置当前会话的隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted; -- 读未提交,下文中出现的RU SET SESSION TRANSACTION ISOLATION LEVEL read committed; -- 读提交,下文中出现的RC SET SESSION TRANSACTION ISOLATION LEVEL repeatable read; -- 可重复读,下文中出现的RR SET SESSION TRANSACTION ISOLATION LEVEL serializable; -- 序列化
-
准备表
-- 建表 CREATE TABLE `AMOUNT` ( `id` int NULL, `money` numeric NULL ) ; -- 插入数据 insert into amount(id,money) values(1, 800); insert into amount(id,money) values(2, 200); insert into amount(id,money) values(3, 1000);
-
事务操作
-- 开启事务 begin; -- 回滚事务 rollback; -- 提交事务 commit;
测试READ UNCOMMITED级别–验证脏读
-
设置当前READ UNCOMMITED隔离级别
-
开启一个客户端称为事务A
-
我们再开启一个客户端称为事务B,注意此时事务A没有提交,可事务B中查询到1号用户少了200
出现了脏读----------事务的修改,即使没有提交,对其他事务也是可见的。即事务可以读取未提交的数据。
- 事务A rollback; 回滚事务
测试READ COMMITED级别–验证不可重复读
-
继续使用RU级别的客户端。修改当前事务为READ COMMITED
-
修改money,没有提交事务
B客户端读到的没有仍是修改前的
-
此时我们提交A事务的修改,此时我们再B客户端执行同样的查询,发现两次查询得到的结果不一致。------不可重复读
commit; -- 提交A事务
测试REPEATABLE READ可重复读级别–验证幻读
-
恢复到最开始的数据,修改当前事务为REPEATABLE READ。
-
A事务添加一条数据,并提交;
第一种情况:在A事务没有commit之前,B事务先查询了一次,查询版本号小于等于当前事务版本号的数据,称作快照读。之后的查询的记录版本号都小于等于当前事务的版本号,因此不论A事务提交与否,B事务的查询结果都不变,而update则把记录修改为当前事务B的版本号,所以下一次的select出现了A事务提交的记录。
第二种情况:B事务开始后没有操作,再A事务commit提交数据后,B事务进行查询,那么会出现A事务提交的数据,这里注意两个事务操作的顺序,B事务select的时间是在A事务commit之后, 因此查询的事务版本号是在B事务commit之后的版本号+1,而第一种情况是B事务的查询在A事务commit之前。
测试SERIALIZABLE
事务串行执行,这里不做演示。