数据库-并发访问带来的问题

安稳与你 提交于 2020-03-20 21:17:32

数据库是一个共享的数据资源。为了提高使用效率,数据库基本上都是多用户的,即允许多个用户并发地访问数据库中的数据,如飞机订票数据库系统、银行储蓄数据库系统等。在这样的系统中,同一时刻并行运行的事务可多达数百个。如果对这种并发访问不加以控制,就会破坏数据的一致性,出现丢失修改、脏读和不可重复读这些问题,如图20.1所示。

丢失修改

脏读

不可重复读

T1

T2

T1

T2

T1

T2

读A=16

 

读A=16

做A=A-4

写回A=12

 

读A=16

 
 

读A=16

 

读A=12

 

读A=16

做A=A-2

写回A=14

做A=A-3

写回A=13

 

撤销

 

读A=14

 
 

做A=A-1

写回A=15

(数据库中最后为15)

(A恢复为16)

(A为12,与数据库中的16不相同)

   

图20.1 并发访问带来的3个问题

一、丢失修改(lost update)

两个事务T1和T2读入同一个数据,并修改,T2提交的修改结果覆盖了T1提交的修改结果,导致T1的修改结果丢失。

例如,如图20.1所示,考虑飞机订票系统中的一个操作序列:

1)       甲售票点(T1事务)读出某航班的机票余额A,此时为16张。

2)       乙售票点(T2事务)读出同一航班的机票余额A,此时也为16张。

3)       甲售票点卖出3张机票,将机票余额A修改成13张,写回数据库。

4)       乙售票点卖出1张机票,将机票余额A修改成15张,写回数据库。

实际上甲、乙两个售票点共卖出4张机票,可数据库中最后显得仅仅是卖出了1张机票。显然,这是由于并发访问所造成的。在上面这种操作序列下,第4)步中乙售票点的修改结果覆盖了第3)步中甲售票点的修改结果,所以导致了这个错误。这就是著名的并发访问中的飞机订票问题。

二、脏读(dirty read)

事务T1更改某一数据,并写入数据库,事务T2读取同一数据,但事务T1由于某种原因被撤销,此时T1更改过的数据恢复原来的值,使T2读取到的值与数据库中的值不相同,只是操作过程中的一个过渡性的、不再需要的、脏的数据,如图20.1所示。

三、不可重复读(non-repeatable read)

事务T1读取数据后,事务T2执行更改操作,使T1无法再现前一次读取的结果。不可重复读包括如下几种情况。

$$ 事务T1读取某一数据之后,事务T2对其进行更改,使T1再次读取该数据时,读取的结果与上次不同,如图20.1所示。

$$ 事务T1按一定条件读取某些数据记录之后,事务T2删除了其中部分记录,使T1按相同的条件再次读取这些数据记录时,发现某些记录不在了。

$$ 事务T1按一定条件读取某些数据记录之后,事务T2插入了一些记录,使T1按相同的条件再次读取这些数据记录时,发现增加了某些记录。

后两种关于记录的不可重复读现象也被称为幻像读(phantom read)现象。

产生上述几种问题的主要原因是由于违反了事务的隔离性原则,发生了事务之间的相互影响。

为了保证并发事务执行的正确性,必须要有一定的机制来保证一个事务的执行不受另一个事务的影响。例如,如果在飞机订票例子中,甲售票点在读出A之后就控制住A,使乙售票点此时无法读取A,直到甲售票点更改 A并将A=13写回数据库后再解除对A的控制为止。这样一来,乙售票点的操作就是在甲售票点的基础上再进行的,就会得出正确的结果A=12,尤其是不会覆盖甲售票点的更改。

“注意”上述问题中的不可重复读、脏读是问题或现象但并非就是错误,在某些情况下是可以接受的。例如,有的统计工作涉及的数据量很大,读到一些脏数据、多读到几行或少读到几行对统计精度没多大影响。为了减少系统开销,可以降低要求。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!