数据库的并发控制

280 阅读6分钟

1、事务的基本概念

所谓事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位

在SQL中定义事务的语句一般有三条

begin transaction
commit  #将事务中所有对数据库的更新写回到磁盘上的物理数据库中去
rollback 

2、事务的ACID特性

原子性:事务是数据库的逻辑工作单位,事务中的操作要么都做,要么都不做

一致性:事务的执行结果必须是使数据库从一个一致性状态变到另一个一致性状态

隔离性:一个事务的执行不能被其他事务干扰

持久性:指一个事务一旦提交,对数据库的改变就是永久的

破坏ACID特性的因素

  • 多个事务并行运行时,不同事务的操作交叉执行

  • 事务在运行过程中被强行停止

3、并发控制概述

在多处理机系统中,每个处理机可以运行一个事务,多个处理机可以同时运行多个多个事务,实现多个事务真正的并行运行。这种并行执行方式称为同时并发方式

并发操作带来的数据库不一致性包括丢失修改,不可重复读,和脏读

3.1、丢失修改

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

T1和T2开始读出机票余额为16张,T1事务中卖出2张机票,余额为14写回数据库,T2事务也卖一张机票,余额为15,余额为15写回数据库,这样卖出三张票,数据还是15

3.2、不可重复读

不可重复读是指事务T1读取数据后,事务T2执行更新操作,导致T1无法再现前一次的读取结果了。有以下三种情况

  • 事务T1读取某一数据后,事务T2对其进行了修改,当事务T1再次读取该数据时,得到了与前一次不同的值。T1读取数据B=100进行一系列运算,T2读取同一数据B,对其进行修改后将B=200写回数据库。T1为了对读取值校对会重读B,B已为200,与第一次读取值不一致

  • 事务T1按一定条件从数据库中读取了某些数据记录后,事务T2删除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记录消失了

  • 事务T1按一定条件从数据库中读取了某些数据记录后,事务T2插入了一些记录,T1再次按相同条件读取数据时,发现多了一些记录。

后两种不可重复读的情况有时也称为幻读

3.3、脏读(读脏数据)

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

4、解决方法

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

并发控制的主要技术有加锁(locking),时间戳(timestamp),乐观控制法(optimistic scheduler)和多版本并发控制(mvcc)

4.1、加锁

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

基本的锁数据类型有两种:排他锁(exclusive locks,简称X锁)和共享锁(share locks,简称S锁)

  • 排他锁又称写锁,事务T对数据对象A加写锁,则只允许T读取和修改A,其他任何事物不能再对A加任何类型的锁,直到T释放了A的锁为止

  • 共享锁又称读锁。若事物T对数据对象A加读锁,则事物T可读A但是不能修改A,其他事务职能再对A加读锁,而不能加写锁,直到T释放A上的读锁为止

4.1.1 加锁协议

在运用X锁和S锁这两种基本封锁对数据对象加锁时,还需要约定一些规则。

例如:何时申请X锁或S锁、持锁时间、何时释放等。

这些规则称为封锁协议。

对并发操作的不正确调度可能会带来丢失修改、不可重复读、脏读等不一致性问题,三级封锁协议分别在不同程度上解决了这些问题

(实际上这个就是数据库的隔离等级,数据库的操作就是读和写,选择不同的场景对读或者写加控制,就避免并发问题)

  • 1、一级封锁协议

指的是事务T在修改数据R之前必须先对其加写锁,直到事务结束(Commit或者RollBack都算结束了)才释放。

例如:事务T1在读数据A之前先对A加锁,当T2请求对A加X锁时被拒绝,T2只能等T1释放A的锁之后对A加X锁,这个时候它读到的A时T1更新好的值

(意思是事务T在写操作前后,其他事务都不能读写数据)

一级封锁协议可以防止丢失修改,并保障了事务T时可以恢复的。

在一级封锁协议中,如果仅仅是读数据而不对其进行修改,是不需要加锁的,所以它不能保障可重复读和不读脏数据

  • 2、二级封锁协议

指在一级封锁协议的基础上增加事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。

例如:事务T1在对数据C进行修改之前,先对C加X锁,修改其值后写回磁盘。这时T2请求在C上加S锁,因T1已经在C上加了X锁,T2只能等待。T1因某种原因被撤销,C恢复为原值,T1释放C上的X锁后T2获得C上S锁,读到正确的C的数据。

(意思是事务T的过程中,其他事务对T处理的数据加S锁,能够保障事务T读到的数据是完成事务操作或者回滚之后的。主要是为了防止事务T的执行失败回滚造成的脏读)

  • 3、三级封锁协议

指在一级封锁协议的基础上增加事务T在读取数据R之前必须对其加S锁,加的S锁直到事务结束之后才能释放

4.1.2 活锁和死锁
4.3 MVCC

多版本并发控制(MultiVersion Concurrency Control,MVCC)是指在数据库中通过维护数据对象的多个版本信息来实现高效并发控制的一种策略