目前数据库MySQL 并发事务下,在不同的隔离级别下,可能会出现四个问题.分别是:脏写(Lost Update),脏读(Dirty Reads),不可重复读(Non-Repeatable Reads),幻读(Phantom Reads)
数据库的隔离级别分别是: 未提交读(read uncommitted)、已提交读(read committed)、可重复读(repeatable read)、串行化(serializable)
1.查看MySQL目前的隔离级别,默认是 可重复读
select @@transaction_isolation;
2.设置当前会话期间的事务隔离级别
set session transaction isolation level 事务隔离级别
set session transaction isolation level REPEATABLE READ;
我们现在来看下,如何复现不同隔离级别下的并发问题
1.脏写:如果一个事务修改了另一个未提交事务修改过的数据,那就意味着发生了脏写
由于脏写问题过于严重,所以每一个事务隔离级别都防止了该情况发生
2.脏读:一个事务已经更新一些数据到数据库,但还没有提交。另一个事务可以看到未提交的数据
该情况需在 隔离级别为:读未提交下才会出现
这个时候发现,在右框开启事务后,修改一条数据,没有显示commit, 在左边就可以查询到还没有提交更新后的数据,这种情况就叫 脏读!
3.不可重复读:这种情况发生 在一个事务内多次读同一数据。A事务查询某条数据,该事务未结束时,B事务也访问同一数据并进行了修改。那么在A事务中的两 次读数据之间,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。
按照上面操作的步骤,可以重现不可重复读的问题
读已提交的隔离级别可以看到,避免了脏读的出现,但是没有避免不可重复读的出现!
这次的事务隔离级别为 可重复读,可以看到避免了 不可重复读的并发问题!
4.虚读 / 幻读 : 事务A在操作一堆数据的时候,事务B插入了一条数据,A事务再次查询,发现多了一条数据,像是幻觉。与不可重复读类似,不同的是一个是修改,一个是新增或者删除。
这个时候发现,在 可重复读的隔离级别下,幻读的情况也解决了?~
我们再看下 另外一种情况
这个时候 我们发现,在可重复读的隔离级别下,并没有完全解决幻读这个问题,他只是解决了读时候的幻读问题, 没有解决 写 的时候的幻读的问题