假设同一个A和B两个同时并发操作数据库,A和B执行的任务如下:从数据库中读取整数N,将N随机加上10或者20,将新的N更新回数据库。这两个并发执行的实例可能发生下面的执行顺序。
(1)A从数据库中读取N,当前数据库中N=0;
(2)B从数据库中读取N,当前数据库中N=0;
(3)A将N加10,并更新入数据库,当前数据库中N=10
(4)B将N 加20,并更新入数据库,当前数据库中N=20;
可以看到由于数据库出现了交叉存取的操作,B所读取的N是过期的版本,即A在写回数据之前的版本。这样当B更新的时候,将会覆盖A的操作,这就是著名的“更新丢失”问题。那么应该如何避免这种情况的发生呢?
解决此类问题的方法就是为数据库加锁,以防止多个组件读取数据,通过锁住事务所用的数据,能保证在打开锁之前,只有本事务才能访问数据。这样就避免了交叉存取的问题。这和操作系统中的PV操作原理类似。
由于锁将其他并发的事务排除在数据库更新之外,所以这会导致性能的严重下降。
为了提高性能,事务将锁分为两种类型:只读锁和写入锁。只读锁是非独占的,多个并发的事务都能获得只读锁;写入锁是独占的,任意时间只能有一个事务可以获得写入锁。