MySQL事务之脏读问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun8112133/article/details/89670009

版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/89670009








在事务的并发操作中,也就是多个事务同时对同一组数据进行操作时,可能会出现脏读、不可重复读、幻读这三个问题,本篇博客就来为大家演示脏读问题。

一、脏读概述

脏读 就是一个事务读到另一个事务没有提交的数据。事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,事务B读到的就是脏数据。

隔离级别 有四种,分别是:读未提交、读已提交、可重复读、序列化。

​  读未提交: Read Uncommitted,顾名思义,就是一个事务可以读取另一个未提交事务的数据。最低级别,它存在3个问题(脏读、不可重复读、幻读)。

​  读已提交: Read Committed,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。 它解决了脏读问题,存在2个问题(不可重复读、幻读)。

​  可重复读: Repeatable Read,就是在开始读取数据(事务开启)时,不再允许修改操作 。它解决了脏读和不可重复读,还存在1个问题(幻读)。

​  序列化: Serializable,序列化,或串行化。就是将每个事务按一定的顺序去执行,它将隔离问题全部解决,但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

大多数数据库默认的事务隔离级别是 Read Committed,比如 SQL Server , Oracle。但 MySQL 的默认隔离级别是 Repeatable Read。

1、事例

老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。

2、分析

实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读,也就是看到了脏的数据。



二、演示脏读

1、新建一个数据库(bank库),并准备一张表(account表)

1、数据库和数据表

2、打开两个窗口,并分别设置自动提交方式为off

show variables like 'autocommit';   – 查看当前的自动提交是否开启

set autocommit = off;   – 将自动提交关闭

2、取消自动提交(A窗口)
2、取消自动提交(B窗口)

3、将A窗口的隔离级别设置成 “读未提交”

select @@tx_isolation;   – 查询当前的隔离级别

set session transaction isolation level read uncommitted;   – 设置当前会话隔离级别为“读未提交”

3、设置隔离级别

4、两个窗口分别开启事务

start transaction;   – 开启事务

4、开启事务

5、在B窗口更改数据,但不要提交事务

update account set money = money - 100 where id = 1;   – 修改account表中id为1的money字段数据

5、更改数据

6、分别在数据库和A窗口中查看数据

select * from account;   – 查看account中的全部数据

6、查看数据(数据库)
6、查看数据(A窗口)

因为B窗口还没有提交事务,所以数据库中的数据是不会发生改变的,这个是正常现象。而下一个现象你会惊喜的发现,A窗口却读到了B窗口更新后但还未提交的数据。这就是A窗口读到了 “脏的数据”,这个现象就是 “脏读”“读未提交” 这种隔离级别会发生 “脏读”、“不可重复读”、“幻读” 这三个问题。有关 “不可重复读”及“幻读” 的问题请参考后续博客。


有关事务的知识可以参考我之前写的博客《【Spring4.0笔记整理十七】Spring事务详解》【Spring4.0笔记整理十八】Spring事务管理详解


博客中若有不恰当的地方,请您一定要告诉我。前路崎岖,望我们可以互相帮助,并肩前行!



猜你喜欢

转载自blog.csdn.net/sun8112133/article/details/89670009