MySQL(26):事务的隔离级别出现问题之 幻读
2016-05-15 09:13
501 查看
1. 幻读
幻读(Phantom Read)又称为虚读,是指在一个事务内两次查询中数据条数不一致,幻读和不重复读有些类型,同样是在两次查询过程中,不同的是,幻读是由于其他事务做了插入记录的操作,导致记录数有所增加。
例如:银行在做统计报表时统计account表中所有用户的总金额时候,此时总共有三个账户,总共金额为3000元,这时候新增了一个用户账户,并且存入1000元,这时候银行再次统计就会发现账户总金额为4000,造成了幻读情况
2. 演示幻读:
(1)首先我们设置b账户的隔离级别
b账户:由于前面将事务个隔离级别设置为可重复读,这种隔离级别是可以避免幻读的出现,因此需要将事务的隔离级别设置为更低,下面将事务的隔离级别设置为
Read Committed,具体语句如下:
上述语句执行完成之后,b账户事务的隔离级别为Read Committed
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515083845273-1634318772.png)
(2)演示幻读:
b账户:首先在b账户中开启一个事务,然后在当前事务中查询账户的余额信息,查询结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515085922336-1844900790.png)
a账户:在对a账户进行添加操作之前,使用select语句查看当前a账户中的信息,执行结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515090127242-1002998463.png)
接下来对a账户进行添加操作,a账户不用开启事务,直接执行添加操作即可,具体语句如下:
执行结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515090549367-1530809750.png)
b账户:当a账户添加记录完成之后,可以在b账户中再次查询场合余额信息,如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515090710445-1180218565.png)
通过对比b账户设置Read Committed隔离级别前后,发现第二次查询数据时比第一查询数据时候多一条记录,这种情况并不是错误的,但可能不符合实际需求。需要注意的是,上述情况演示完成之后,将b账户中的事务提交。
3. 解决问题:
(1)重新设置b账户的隔离级别
b账户:为了防止出现幻读,可以将b账户的隔离级别设置为Repeatable Read,具体语句如下:
上述的语句执行完毕之后,事务隔离级别设置为Repeatable Read
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515110342773-2022930103.png)
(2)重新验证是否出现幻读
b账户:在b账户中重新开启一个事务,并在该事务中查询当前账户的余额信息,查询结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515110513273-308945826.png)
a账户:对a账户进行添加操作之前,使用select语句查看当前的a账户的余额信息,执行语句结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515110731414-1173353539.png)
接下来对账户a进行添加操作,在a账户中不开启事务,直接执行添加操作,具体语句如下:
执行结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515111249914-1865082044.png)
b账户:当a账户的添加操作执行成功之后,再次查询当前账户的余额信息,查询结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515111415148-515692006.png)
对比b账户两次查询的结果,发现两者都是一致的。并没有出现重复读取的情况,因此可以说明当前事务的隔离级别可以避免幻读,最后还有使用commit语句提交当前事务,提交之后,b账户查询结果如下:
幻读(Phantom Read)又称为虚读,是指在一个事务内两次查询中数据条数不一致,幻读和不重复读有些类型,同样是在两次查询过程中,不同的是,幻读是由于其他事务做了插入记录的操作,导致记录数有所增加。
例如:银行在做统计报表时统计account表中所有用户的总金额时候,此时总共有三个账户,总共金额为3000元,这时候新增了一个用户账户,并且存入1000元,这时候银行再次统计就会发现账户总金额为4000,造成了幻读情况
2. 演示幻读:
(1)首先我们设置b账户的隔离级别
b账户:由于前面将事务个隔离级别设置为可重复读,这种隔离级别是可以避免幻读的出现,因此需要将事务的隔离级别设置为更低,下面将事务的隔离级别设置为
Read Committed,具体语句如下:
set session transaction isolation level read committed;
上述语句执行完成之后,b账户事务的隔离级别为Read Committed
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515083845273-1634318772.png)
(2)演示幻读:
b账户:首先在b账户中开启一个事务,然后在当前事务中查询账户的余额信息,查询结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515085922336-1844900790.png)
a账户:在对a账户进行添加操作之前,使用select语句查看当前a账户中的信息,执行结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515090127242-1002998463.png)
接下来对a账户进行添加操作,a账户不用开启事务,直接执行添加操作即可,具体语句如下:
insert into account(name,money) values('c',1000);
执行结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515090549367-1530809750.png)
b账户:当a账户添加记录完成之后,可以在b账户中再次查询场合余额信息,如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515090710445-1180218565.png)
通过对比b账户设置Read Committed隔离级别前后,发现第二次查询数据时比第一查询数据时候多一条记录,这种情况并不是错误的,但可能不符合实际需求。需要注意的是,上述情况演示完成之后,将b账户中的事务提交。
3. 解决问题:
(1)重新设置b账户的隔离级别
b账户:为了防止出现幻读,可以将b账户的隔离级别设置为Repeatable Read,具体语句如下:
set session transaction isolation level repeatable read;
上述的语句执行完毕之后,事务隔离级别设置为Repeatable Read
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515110342773-2022930103.png)
(2)重新验证是否出现幻读
b账户:在b账户中重新开启一个事务,并在该事务中查询当前账户的余额信息,查询结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515110513273-308945826.png)
a账户:对a账户进行添加操作之前,使用select语句查看当前的a账户的余额信息,执行语句结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515110731414-1173353539.png)
接下来对账户a进行添加操作,在a账户中不开启事务,直接执行添加操作,具体语句如下:
insert into account(name,money) values('d',1000);
执行结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515111249914-1865082044.png)
b账户:当a账户的添加操作执行成功之后,再次查询当前账户的余额信息,查询结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515111415148-515692006.png)
对比b账户两次查询的结果,发现两者都是一致的。并没有出现重复读取的情况,因此可以说明当前事务的隔离级别可以避免幻读,最后还有使用commit语句提交当前事务,提交之后,b账户查询结果如下:
![](https://images2015.cnblogs.com/blog/757858/201605/757858-20160515111754164-2117699227.png)
相关文章推荐
- mysql常见问题之添加服务与配置
- mysql启动报错:Table 'mysql.host' doesn't exist
- MySQL(25):事务的隔离级别出现问题之 不可重复读
- MySQL ALTER讲解
- Windows系统搭建Mysql Cluster集群
- mysql 笔记
- 如何允许外网可以连接mysql数据库
- 好用的mysql数据字典工具
- mysql数据字典
- MySQL 数据库 ALTER命令讲解
- MySQL ALTER命令使用详解
- 处理Zabbixl历史数据库解决办法三---使用MySQL中间件为Zabbix数据库扩容
- mysql数据库表的基本操作
- Zabbix proxy服务器磁盘IO持续报警
- MySql Service 安装流程,包含解决服务无法启动 服务没有报告任何错误
- mysql数据库处理乱码
- Mysql存储引擎
- Oneproxy 读写分离
- 一条SQL搞挂mysql案例一则
- MySQL更新用户密码