MySQL脏读的演示
1.查询和设置隔离级别
show variables like '%isolation%';
-- 或
select @@tx_isolation;
2.设置事务隔离级别
需要退出MySQL再进入MySQL才能看到隔离级别的变化
set global transaction isolation level 隔离级别;
安全性:serializable > repeatable read > read committed > read uncommitted
性能 : serializable < repeatable read < read committed < read uncommitted
set global transaction isolation level read uncommitted;
set global transaction isolation level repeatable read;
注意,mysql5.6后如果将隔离级别设置uncommitted,那么修改数据会报错,
所以我们在演示的时候,针对当前会话设置如下:
# 设置session级别的BINLOG
SET SESSION binlog_format = 'MIXED' ;
上述命令只是当前会话有效,重新连接失效,通过如下命令可以查看:
#查看binlog方式
mysq
3.脏读的演示
脏读:一个事务读取到了另一个事务中尚未提交的数据。
打开一个窗口,设置为A窗口,登录MySQL,设置全局的隔离级别为最低
-- 设置窗口名字A
title A
-- 登录mysql数据库
mysql -u root -P 3309 -p
******
-- 设置事务隔离级别
set global transaction isolation level read uncommitted;
注意:设置事务隔离级别,需要重新打开一个窗口才能看到隔离级别的变化.
重新打开一个新的窗口,设置为B窗口,登录MySQL
-- 设置窗口名字B
title B
-- 登录mysql数据库
mysql -u root -P 3309 -p
******
-- 查询隔离级别
select @@tx_isolation;
3.AB窗口都开启事务
4.A窗口更新2个人的账户数据,未提交
update tb_account set money=money-500 where id=1;
update tb_account set money=money+500 where id=2;
5.B窗口查询账户
select *from tb_account;
显然 B已经读到了A尚未提交的数据
6.A窗口回滚
rollback;
7.B窗口查询账户,钱没了
select *from tb_account;
脏读非常危险的,假设我是淘宝阿里后台工程师 我有这个权限,我开启事务, 我双十一在淘宝买了一把阿米洛的键盘,向商家付款700元,商家一看,钱到账了,随后商家开始发货,我收到货后回滚事务,商家一看,XX,钱没了,
解决脏读的问题:将全局的隔离级别进行提升
在A窗口设置全局的隔离级别为read committed
set global transaction isolation level read committed;
B窗口退出MySQL,B窗口再进入MySQL
AB窗口同时开启事务
A更新2个人的账户,未提交
update tb_account set money=money-500 where id=1;
update tb_account set money=money+500 where id=2;
B窗口查询账户
可以看到 B没有读取到A未提交的数据
A窗口commit提交事务
B窗口查看账户
可以看到 但A提交后 B能成功读取提交后的数据
结论:read committed的方式可以避免脏读的发生
小结
- 查询全局事务隔离级别?
show variables like '%isolation%';
select @@tx_isolation;
- 设置全局事务隔离级别?
set global transaction isolation level 隔离级别字符串;
set global transaction isolation level repeatable read;
- 如何解决赃读?
将隔离级别设置为:read committed