版权声明:本文为 小异常 原创文章,非商用自由转载-保持署名-注明出处,谢谢!
本文网址:https://blog.csdn.net/sun8112133/article/details/89670009
文章目录
在事务的并发操作中,也就是多个事务同时对同一组数据进行操作时,可能会出现脏读、不可重复读、幻读、丢失更新这四个问题,本篇博客就来为大家讲解 脏读 问题。
一、脏读概述
脏读 就是一个事务读到另一个事务没有提交的数据。事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,事务B读到的就是脏数据。
隔离级别 有四种,分别是:读未提交、读已提交、可重复读、序列化。
读未提交: Read Uncommitted,顾名思义,就是一个事务可以读取另一个未提交事务的数据。最低级别,它存在4个常见问题(脏读、不可重复读、幻读、丢失更新)。
读已提交: Read Committed,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。 它解决了脏读问题,存在3个常见问题(不可重复读、幻读、丢失更新)。
可重复读: Repeatable Read,就是在开始读取数据(事务开启)时,不再允许修改操作 。它解决了脏读和不可重复读,还存在2个常见问题(幻读、丢失更新)。
序列化: 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表)

2、打开两个窗口,并分别设置自动提交方式为off
show variables like 'autocommit';
– 查看当前的自动提交是否开启
set autocommit = off;
– 将自动提交关闭


3、将A窗口的隔离级别设置成 “读未提交”
select @@tx_isolation;
– 查询当前的隔离级别
set session transaction isolation level read uncommitted;
– 设置当前会话隔离级别为“读未提交”

4、两个窗口分别开启事务
start transaction;
– 开启事务 或begin;
也可以显式开启事务

5、在B窗口更改数据,但不要提交事务
update account set money = money - 100 where id = 1;
– 修改account表中id为1的money字段数据

6、分别在数据库和A窗口中查看数据
select * from account;
– 查看account中的全部数据


因为B窗口还没有提交事务,所以数据库中的数据是不会发生改变的,这个是正常现象。而下一个现象你会惊喜的发现,A窗口却读到了B窗口更新后但还未提交的数据。这就是A窗口读到了 “脏的数据”,这个现象就是 “脏读”,“读未提交” 这种隔离级别会发生 “脏读”、“不可重复读”、“幻读”、“丢失更新” 这四个问题。有关 “不可重复读”、“幻读”及“丢失更新” 的问题请参考后续博客。
有关事务的知识可以参考我之前写的博客《【Spring4.0笔记整理十七】Spring事务详解》 及 【Spring4.0笔记整理十八】Spring事务管理详解 。