vlambda博客
学习文章列表

实例演示mysql的四种事务隔离级别

说明

事务隔离级别
说明
问题
READ UNCOMMITTED
读未提交
脏读
READ COMMITTED
读已提交
不可重复读
REPEATABLE READ
可重复读
幻读
SERIALIZABLE 序列化/串行化 阻塞

mysql的默认事务隔离级别是REPEATABLE-READ,查看当前数据库的事务级别可以用指令:show variables like '%isolation%';,如图1结果。实验环境系统为win10,mysql 版本为:Server version: 8.0.11 MySQL Community Server - GPL,操作工具为win下的cmd窗口。

图1 查看本地mysql的默认事务隔离级别


操作步骤

1.win下打开两个cmd窗口,模拟连接mysql的两个客户端,之所以说模拟,因为描述为两个相互独立的mysql session(会话)会合适些,登录mysql指令:mysql -h localhost -u root -ptgy123


2.使用test库,操作指令:use test;创建实验用表以及插入数据,具体见下文。


3.修改两个客户端的数据库事务隔离级别,进行实验验证。


表建语句

#建表语句

create table t_student(

  id bigint primary key comment '学生主键ID',

  num varchar(32) comment '学号',

  stuName varchar(100) comment '学生姓名'

)engine=innodb default charset=utf8;


#插入语句

insert into t_student(id,num,stuName) values(1000,'No.2014001','唐僧');

insert into t_student(id,num,stuName) values(2000,'No.2014002','孙悟空');

insert into t_student(id,num,stuName) values(3000,'No.2014003','猪八戒');


设置事务隔离级别为READ UNCOMMITTED

a.在两个客户端设置事务隔离级别为读未提交。操作指令为:

 set session transaction isolation level read uncommitted;

b.在客户端1进行事务操作、插入操作、查询操作、但是不提交,操作指令:

实例演示mysql的四种事务隔离级别

图2-1 客户端1操作

c.在客户端2开始事务、进行查询操作,观察结果。

实例演示mysql的四种事务隔离级别

图2-2 客户端2操作

总结:从图2-2我们可以看到对于客户端1未提交的记录“白龙马”,客户端2查询到了,产生了脏读(例如客户端1回滚了插入操作)。实验完毕,两个客户端执行提交指令:commit;结束事务。


设置事务隔离级别为READ COMMITTED

a.设置两个客户端的事务隔离级别为读提交,操作指令:set session transaction isolation level read committed; 。

b.客户端1开始事务、插入数据、查询操作、不提交,客户端2开始事务,查询操作;客户端1提交事务、查询操作,客户端2查询操作。操作执行见图3-1,图3-2:

实例演示mysql的四种事务隔离级别

图3-1 客户端1的操作未提交,客户端2查询结果


实例演示mysql的四种事务隔离级别

图3-2 客户端1的操作提交,客户端2查询结果


总结:客户端1未提交时,客户端2没有查询到“白骨精”这条记录;当客户端1提交后,客户端2查询到了“白骨精”这条记录。由于客户端2在没有进行事务提交的情况下,两次查询到了不同的结果集,故认为是不可重复读。


设置事务隔离级别为REPEATABLE READ

a.设置两个客户端的事务隔离级别为可重复读,操作指令: set session transaction isolation level repeatable read; 。

b.客户端1开始事务、插入操作、查询操作、不提交,客户端2开始事务,查询操作;客户端1提交事务,查询操作,客户端2不提交事务,查询操作;客户端2提交事务,查询操作。操作执行见图4-1,图4-2,图4-3。

实例演示mysql的四种事务隔离级别

图4-1 客户端1未提交,客户端2查询

实例演示mysql的四种事务隔离级别

图4-2 客户端1提交,客户端2查询

实例演示mysql的四种事务隔离级别

图4-3 客户端2提交,查询


总结:可重复读能够保障客户端2的事务在客户端1提交前后读取一致的行为:客户端1事务未提交,客户端2未读取到新增记录“蜘蛛精”;客户端1提交,客户端2未读取到新增记录“蜘蛛精”;客户端1提交,客户端2提交,读取到新增记录“蜘蛛精”。但是可重复读存在幻读问题,比如客户端1提交了新增记录“蜘蛛精”,客户端2未提交事务,且同样插入一条蜘蛛精记录,但是由于主键是唯一的,客户端2是无法插入蜘蛛精记录的,但是在客户端2确实又看不到数据库里的新增记录蜘蛛精,于是就产生了类似“幻觉”的行为。


设置事务隔离级别为SERIALIZABLE

a.设置两个客户端的隔离级别为序列化/串行化,操作指令: set session transaction isolation level serializable;

b.客户端1开始事务、执行更新操作、查询操作,客户端2开始事务,查询操作。操作执行见图5-1,5-2:

图5-1 客户端1未提交,客户端2查询在等待中锁超时报错了

图5-2 客户端1提交,客户端2查询到了更新结果“美女大蜘蛛精”


总结:序列化、串行化读是最安全的事务隔离级别,但是由于串行执行,会阻塞报错锁超时,效率较低。