在数据库系统中,多个事务并行执行时,针对不同隔离级别,会出现集中不同的问题,主要是:脏读、不可重复读、幻读。

数据库隔离级别

1,read uncommitted 隔离级别最低,即允许读取未提交事务的数据
2,read committed 不允许读取未提交的数据行,所以不会出现脏读
3,REPEATABLE_READ 锁定所读取的所有行,但是并不能防止插入操作,还是出现幻读
4,SERIALIZABLE 串行执行事务,也就不可能出现上述的问题。
查看当前数据库隔离界别:select @@tx_isolation

隔离级别和问题

各种不同级别可能出现的不同问题:

隔离级别            脏读    不可重复读    幻读
READ-UNCOMMITTED    √      √           √
READ-COMMITTED    ×      √           √
REPEATABLE-READ    ×      ×           √
SERIALIZABLE    ×      ×           ×

脏读

脏读会出现在read uncommitted级别。
两个SESSION A B,SESSION A 读取 SESSION B 还会提交的数据。

SESSION A:BEGIN
SESSION B:BEGIN
SESSION B:UPDATE TABLE set a = a + 1 where id = 1
SESSION A:SELECT * from TABLE where id = 1

这种情况即脏读,SESSION A 在事务B还未提交的情况下,读取了id = 1的数据。如果这种情况B因为特殊原因回滚了,那么A得到的信息就是不对的。

不可重复读

不可重复度会出现在前两个级别。不可重复读是指在SESSION A 两次读取的操作中,得到的结果竟然是不一样的。这种情况事务B已经提交,所以不算脏读。有的系统中,不可重复读其实是允许的。不可重复读锁住读取的行即可解决,即A在读取某行的时候,不允许B或其他事务修改。

幻读

可以理解为特殊的不可重复读,虽然A在读取某行的时候加了排它锁,但是并不能阻止其他事务插入数据。那么当在事务A读取统一条件的读的时候,虽然用了排它锁行锁、gap锁,但是不能阻止插入操作。即当A事务第二次读取的时候,突然出现了一条记录,好似幻觉。如果事务A这个时候插入数据,如果有自增ID,那么这个时候会直接因为dulipcate ID而报错。
这种情况可以锁表。

https://github.com/Snailclimb/JavaGuide/blob/master/docs/database/%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E7%BA%A7%E5%88%AB(%E5%9B%BE%E6%96%87%E8%AF%A6%E8%A7%A3).md
http://www.luxinzhi.com/database/502.html
http://hedengcheng.com/?p=771
https://www.0php.net/posts/MySQL-%E4%BA%8B%E5%8A%A1%E9%9A%94%E7%A6%BB%E5%AE%9E%E9%AA%8C-%E8%AE%A4%E8%AF%86%EF%BC%9A%E8%84%8F%E8%AF%BB%E3%80%81%E4%B8%8D%E5%8F%AF%E9%87%8D%E5%A4%8D%E8%AF%BB%E3%80%81%E5%B9%BB%E8%AF%BB.html