数据库并发操作会引发的问题

多个事务背景:MySQL5.6 InnoDB存储引擎,事务隔离级别最低的read uncommited(为了看到各种异常)。
多个事务同时访问数据库时候,会发生下列5类问题,包括3类数据读问题(脏读,不可重复读,幻读),2类数据更新问题(第一类丢失更新,第二类丢失更新):

脏读(dirty read)

A事务读取B事务尚未提交的更改数据,并在这个数据基础上操作。如果B事务回滚,那么A事务读到的数据根本不是合法的,称为脏读。在oracle中,由于有version控制,不会出现脏读。数据库事务隔离级别高于 read commited即可

MySql事务在并发情况下出现的异常及解决方法
理论库存应当有9个,但由于脏读(T4时查出库存9个即为脏读),现有8个
不可重复读(unrepeatable read)

 A事务读取了B事务已经提交的更改(或删除)数据。比如A事务第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。将数据库事务隔离级别设为repeatable read即可

MySql事务在并发情况下出现的异常及解决方法
事务A在T2和T4读出的数据不同,即是不可重复度

幻读(phantom read)

A事务读取了B事务已经提交的新增数据。注意和不可重复读的区别,这里是新增,不可重复读是更改(或删除)。这两种情况对策是不一样的,对于不可重复读,只需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必须加表级锁,防止在这个表中新增一条数据(PS:对于锁的问题请自行查找或关注我的后续文章)。
当然,也可以将数据库事务隔离级别设为serializable,但一般不这样做,因为该策略是完全阻塞的,将对数据库的访问完全序列化,并发性能最差。

MySql事务在并发情况下出现的异常及解决方法
T5时数据莫名其妙有了,就是幻读现象。如果A事务只进行读操作,不进行写操作,将数据库事务隔离级别设为repeatable read,并用start transaction with consistent snapshot开启事务,同时进行快照读,也可以防止幻读现象(因为在可重读策略下,不是开启事务就建立快照点,而是在第一次查询时建立快照点)。
丢失更新

 第一类丢失更新:A事务提交时,把已提交的B事务的数据覆盖掉。
 第二类丢失更新:A事务回滚时,把已提交的B事务的数据覆盖掉。  

第一类
MySql事务在并发情况下出现的异常及解决方法
理论库存是7个,但现在剩余8个;
第二类
MySql事务在并发情况下出现的异常及解决方法
理论库存是9个,但现在剩余10个;
丢失更新完全靠事务是无法解决的,此时就需要结合数据库悲观锁来防止此类问题,操作如下:
//0.开始事务

begin;/begin work;/start transaction; (三者选一就可以)

//1.查询出商品信息

select status from t_goods where id=1 for update;(添加排他锁)

//2.根据商品信息生成订单

insert into t_orders (id,goods_id) values (null,1);

//3.修改商品status为2

update t_goods set status=2;

//4.提交事务

commit;/commit work;

相关文章:

  • 2021-08-13
  • 2021-07-21
  • 2021-10-05
  • 2022-12-23
  • 2022-12-23
  • 2021-07-23
  • 2022-01-09
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-02-02
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案