前言
大家应该都知道MySQL四种隔离级别分别是读未提交,读已提交,可重复读,串行化,可能大家通过书籍或者博客对着四种隔离级别的事务读取结果都知道。本文主要通过具体例子来验证这四种隔离级别的区别,让大家更加清晰看出不同的。
举个例子:如下,两个事务分别执行,四种不同隔离级别的,事务 A 会有哪些不同的返回结果,也就是图里面 V1、V2、V3 的返回值分别是什么?
实例演示
接下来我们按照不同的隔离级别来分析不同的结果:
在分析前,须知道如下命令:
-- 查看隔离级别
show variables like 'transaction_isolation';
-- 设置隔离级别0-3,设置完之后必须重新打开查询条件
set transaction_isolation=2;
-- 设置全局隔离级别
show global variables like 'transaction_isolation';
模拟上述操作:
开启两个查询窗口,分别执行如下命令,关闭自动提交事务,并开启事务:
set autocommit=0;
BEGIN;
事务一:
set autocommit=0;
BEGIN;
# 先执行如下查询
SELECT `name` from t WHERE id = 1;
# 等待事务二更新之后查询(事务二未提交)
SELECT `name` v1 from t WHERE id = 1;
# 事务二提交之后再次查询
SELECT `name` v2 from t WHERE id = 1;
COMMIT;
SELECT `name` v3 from t WHERE id = 1;
事务二:
set autocommit=0;
BEGIN;
# 事务一第一次查询后执行
UPDATE t set `name` = '2' WHERE id = 1;
COMMIT;
准备一个表,数据如下:
1.读未提交
设置隔离级别为读未提交
set global transaction_isolation=0;
事务二执行更新之后,事务执行第二次查询,发现变为2了
很显然,等待事务二提交,事务一再一次查询,v2肯定也是2
所以最终结果, 则V1 的值就是 2。这时候事务 B 虽然还没有提交,但是结果已经被 A 看到了。因此,V2、V3 也都是 2。
2.读已提交
设置隔离级别为读已提交
set transaction_isolation=1;
事务二执行更新之后,事务执行第二次查询,发现v1还是1了
事务二提交,事务一再一次查询,v2变成了2。验证了读已提交的隔离级别。
所以最终结果,则 V1 是 1(B事务未提交读不到)。V2 的值是 2,事务 B 的更新在提交后才能被 A看到。显然, V3 的值也是 2。
3.可重复读
设置隔离级别为可重复读
set transaction_isolation=2;
则 V1、V2 是 1,V3 是 2(事务一结束了)。之所以 V2 还是 1,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。
4.串行化(锁)
设置隔离级别
set global transaction_isolation=3;
事务一开启之后,执行查询v1,之后事务二执行更新操作,发现事务二被阻塞了,也就被加锁了,指定事务一commit之后,释放锁,才可以执行。
所以,name的值是不会被事务二更新的,查询v2,v3都是1
当事务一commit之后,事务二才可以执行
这时候查询v3,已经是事务一和事务二都提交了,所以是最新值为2
最终结果,事务 二 执行“将 1 改成 2”的时候,会被锁住。直到事务 一提交后,事务 二 才可以继续执行。所以从 事务一 的角度看, V1、V2 值是 1,V3 的值是 2。
注意:每次修改隔离级别之后,最后关闭当前查询窗口
评论区