并发一致性问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发一致性问题相关的知识,希望对你有一定的参考价值。

并发一致性问题

常见并发并发一致性问题包括:丢失的修改、不可重复读、读脏数据、幻影读(幻影读在一些资料中往往与不可重复读归为一类)。

丢失修改

下面我们先来看一个例子,说明并发操作带来的数据的不一致性问题。

考虑飞机订票系统中的一个活动序列:

  1. 甲售票点(甲事务)读出某航班的机票余额A,设A=16.
  2. 乙售票点(乙事务)读出同一航班的机票余额A,也为16.
  3. 甲售票点卖出一张机票,修改余额A←A-1.所以A为15,把A写回数据库.
  4. 乙售票点也卖出一张机票,修改余额A←A-1.所以A为15,把A写回数据库.

结果明明卖出两张机票,数据库中机票余额只减少1。

归纳起来就是:两个事务T1和T2读入同一数据并修改,T2提交的结果破坏了T1提交的结果,导致T1的修改被丢失。前文(2.1.4数据删除与更新)中提到的问题及解决办法往往是针对此类并发问题的。但仍然有几类问题通过上面的方法解决不了,那就是:

不可重复读

不可重复读是指事务T1读取数据后,事务T2执行更新操作,使T1无法再现前一次读取结果。具体地讲,不可重复读包括三种情况:

  • 事务T1读取某一数据后,事务T2对其做了修改,当事务1再次读该数据时,得到与前一次不同的值。例如,T1读取B=100进行运算,T2读取同一数据B,对其进行修改后将B=200写回数据库。T1为了对读取值校对重读B,B已为200,与第一次读取值不一致。
  • 事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录神密地消失了。
  • 事务T1按一定条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录。(这也叫做幻影读)

读"脏"数据

读"脏"数据是指事务T1修改某一数据,并将其写回磁盘,事务T2读取同一数据后,T1由于某种原因被撤消,这时T1已修改过的数据恢复原值,T2读到的数据就与数据库中的数据不一致,则T2读到的数据就为"脏"数据,即不正确的数据。

产生上述三类数据不一致性的主要原因是并发操作破坏了事务的隔离性。并发控制就是要用正确的方式调度并发操作,使一个用户事务的执行不受其它事务的干扰,从而避免造成数据的不一致性。

 

并发一致性问题的解决办法

 封锁(Locking)

封锁是实现并发控制的一个非常重要的技术。所谓封锁就是事务T在对某个数据对象例如表、记录等操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象。

基本的封锁类型有两种:排它锁(Exclusive locks 简记为X锁)和共享锁(Share locks 简记为S锁)。

排它锁又称为写锁。若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。这就保证了其它事务在T释放A上的锁之前不能再读取和修改A。

共享锁又称为读锁。若事务T对数据对象A加上S锁,则其它事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其它事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

以上是关于并发一致性问题的主要内容,如果未能解决你的问题,请参考以下文章

数据库系统原理---并发一致性问题

大厂面试01期高并发场景下,如何保证缓存与数据库一致性?

大厂面试01期高并发场景下,如何保证缓存与数据库一致性?

1.3 事物和并发一致性问题

Java 并发MESI缓存一致性协议

并发扣款一致性,幂等性问题,这个话题还没聊完!!!