要理解幻读、脏读、不可重复读,必须先搞清楚事务的隔离级别
事务隔离级别
数据库事务的隔离级别有4个,由低到高依次为Read uncommitted 、Read committed 、Repeatable read 、Serializable ,这四个级别可以逐个解决脏读 、不可重复读 、幻读 这几类问题。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |
脏读
当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
脏读就是读到其他事务未提交的数据
数据库的事务默认一般都是Read committed,所以脏读现象很少发生
不可重复读
在一个事务内,对同一条数据进去读取,第一次读取到的数据和第二次读取到的数据不一致
产生不可重复读的原因是,在两次读取数据之间,数据被其他事务修改了;第二次读取的时候,读取到了其他事务已提交的数据,发现前后两次数据不一致了(即不能读到相同的数据)
解决办法
解决办法是,在第一次读取时,就锁定资源,不让其他事务修改
幻读
已读取的数据,在事务过程中被其他事务修改,在本事务两次读取的数据不一致
在一个事务内,第一次读取到的数据条数和第二次读取到的数据条数不一致
产生幻读的原因是:在两次读取数据之间,其他数据插入了新的数据;第二次读取到的数据总数和第一次不一致(就像幻觉一样)
解决办法
幻读现象一般不解决,在业务代码上做判断即可;如果一定要解决,就只能锁定所有相关的资源,锁表或者增加分布式锁,插入时也必须得到锁才能操作
总结
脏读很好理解,就是读到其他事务未提交的数据
那么不可重复读和幻读到底有什么区别呢,看起来好像差不多
- 不可重复读,指的是同一条记录两次查询中被其他事务修改了;
- 幻读,指的是两次查询中,其他事务插入了新数据