数据库的各种隔离级别和存在的问题

了解了数据库事务的隔离级别,知道在什么隔离级别下会存在哪些问题。根据不同业务对数据一致性的不同需求,在当前数据库隔离级别不能保证数据一致性的情况下,合理的编写程序代码,必要的地方加锁,才能保证程序正确运行。

假设有一个账户(account = 123)买书的事务A业务逻辑是:

1、开启事务。

2、查询账户余额是否充足,能买100元的图书。

3、如果余额充足,创建购买图书的订单。

4、更新账户余额扣减100账户余额。

5、提交事务。

在各种数据库隔离级别下会发生什么问题?

隔离级别:读未提交

如果隔离级别为读未提交,有另一个事务B:

1、开启事务。

2、扣减100账户余额。

3、事务回滚。

当事务A执行完第二步检查账户余额充足创建了订单后,事务B开始执行,事务B执行完第二步扣减账户余额后,账户余额为0,事务A在扣减余额时,因为隔离级别为读未提交,事务A查询到了事务B没有提交的修改,更新余额为-100,最终事务B 回滚了,但是账户余额被A事务错误计算为了-100,这就是因为数据库隔离级别为读未提交,发生了一个事务读取到了另一个事务未提交的数据,这就是脏读问题。

隔离级别:读已提交

如果隔离级别为读已提交,就能避免上一个场景的脏读问题,这时候如果把事务B修改为:

1、开启事务。

2、扣减100账户余额。

3、提交事务。

最后一步修改为提交事务才能对事务A造成影响。这样的话当事务A创建了订单后,事务B开始执行并提交了事务,扣减账户余额为0,事务A读取到了事务B提交后的结果后,继续更新账户余额为-100,虽然账户余额是对的,但是最终导致账户余额被扣成了负的,事务A的第二步检查账户余额失去了意义。事务A开始检查过账户余额充足但是读取到了事务B提交的结果,同一个事务A两次查询结果不一致,这就是不可重复读问题。

隔离级别:可重复读

如果隔离级别为可重复读,当A开始事务创建订单后,账户表的(account = '123’的这条数据被锁定了),事务B得等到事务A提交才能修改,就避免了上一个不可重复读的问题。这时候假如有另一个事务C是:

1、开启事务。

2、查询账户的交易记录数。

3、打印所有的交易记录数。

4、提交事务。

当事务A提交后事务C查询交易记录数为1,这时候事务B执行并提交了,事务C打印交易记录,却打印出了两条,同一个事务C内多次查询返回的结果集(交易记录条数)不一样,这就是幻读

隔离级别:串行化

事务串行执行。可以避免以上脏读、不可重复读、幻读问题。但是效率低下。

总结

oracle的默认隔离级别是:读已提交
mysql的默认隔离级别是:可重复读
了解了数据库事务的隔离级别,知道在什么隔离级别下会存在哪些问题。根据不同业务对数据一致性的不同需求,在当前数据库隔离级别不能保证数据一致性的情况下,合理的编写程序代码,必要的地方加锁,才能保证程序正确运行。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值