12.1 并发控制概述
并发控制是指数据库管理系统(DBMS)通过控制多个事务同时执行,保证数据的一致性和隔离性,避免事务间的相互干扰。
事务串行执行不能充分利用系统资源
并发执行的优点:能够减少处理机的空闲 时间,提高系统的效率
并发执行可能引发的问题
会产生多个事务同时存取同一数据的情况可能会存取和存储不正确的数据,破坏事务一致性和数据库的一致性
丢失修改(Lost Update)
两个事务对同一数据进行更新,其中一个事务的更新被覆盖
读“脏”数据(Dirty Read)
一个事务读取到另一个未提交事务修改的数据
不可重复读(Non-Repeatable Read)
一个事务在多次读取同一数据时,由于其他事务的修改,导致读取的结果不一致
幻读(Phantom Read)
一个事务在多次查询时,结果集因其他事务的插入或删除发生变化
幻读也称作幻影(phantom row)现象,是指事务T1读取数据后,事务T2执行插入或删除操作,使T1无法再现前一次读取结果。
(1)事务T1按一定条件从数据库中读取某些数据记录后,事务T2删 除了其中部分记录,当T1再次按相同条件读取数据时,发现某些记 录“神秘地”消失了。
(2)事务T1按一定条件从数据库中读取某些数据记录后,事务T2插 入了一些记录,当T1再次按相同条件读取数据时,发现多了一些记录
数据不一致性原因:由于并发操作破坏了事务的隔离性
并发控制就是要用正确的方式调度并发操作,使一个 用户事务的执行不受其他事务的干扰,从而避免造成数据 的不一致性
12.2 事务的隔离级别
事务隔离级别定义了一个事务与其他事务之间的隔离程度。SQL标准定义了以下四种隔离级别:

读未提交(Read Uncommitted)
“读未提交”是允许一个事务可以读取另一个未提交事务正在修改的数据。(允许读,不允许写)
存在问题:可能出现 脏读、不可重复读、幻读。
读已提交(Read Committed)
只允许一个事务读其他事务已提交的数据。显然, “读已提交”可以有效避免读脏读
存在问题:不可重复读、幻读
可重复读(Repeatable Read)
“可重复读”是一个事务开始读取数据后,其他事务就不能再对该数据执行UPDATE操作了。
存在问题:幻读。
可串行化(Serializable)
最严格的隔离级别
事务按顺序逐一执行,完全避免了并发问题。
存在问题:性能开销较大。
事务隔离级别并不是越高越好 ,应根据应用的特点和需求选择合适的事务隔离级别
MySql的默认级别是“可重复读"
12.3 封锁
商用的DBMS一般都采用封锁方法
封锁是一种常见的并发控制机制,用于保证事务隔离性。
封锁就是事务T在对某个数据对象(例如表、记录等)操 作之前,先向系统发出请求,对其加锁
加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象
封锁的类型
-
排他锁(X锁):又称为写锁,允许事务读取和修改数据,但其它任何事务都不能再对A加任何类型的锁,
直到T释放A上的锁 -
共享锁(S锁):又称为读锁,允许多个事务同时读取数据,但不能修改。若事务T对数据对象A加上S锁,则其它事务只能再对A 加S锁,而不能加X锁,直到T释放A上的S锁
封锁的粒度
-
表级封锁:对整个表加锁,适用于大批量操作,但并发度低。
-
行级封锁:对表中某一行加锁,并发度高,但开销较大。
12.4 封锁协议
封锁协议是事务加锁与解锁的规则【何时申请X锁或S锁 ,持锁时间 ,何时释放】
对封锁方式规定不同的规则,就形成了各种不同的封锁协议
三级封锁协议
一级封锁协议
事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。
正常结束(COMMIT) ;非正常结束(ROLLBACK)
可防止丢失修改
二级封锁协议
一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁
可以防止丢失修改和读“脏”数据
三级封锁协议
可以解决4个问题
12.5 活锁与死锁
1. 活锁(Livelock):事务虽然在持续执行,但由于不断被让步,导致无法继续完成自己的任务。
-
原因:频繁的资源让步或优先级调度机制。
-
解决方法:采用公平调度策略。引入随机性,避免资源竞争的循环。
2. 死锁(Deadlock):两个或多个事务因相互持有对方需要的资源,导致相互等待,无法继续执行。
解决方法:死锁预防:采用一次性申请所有资源策略。规定加锁顺序,避免循环等待
死锁检测与解除:定期检测等待图,发现死锁后中止某个事务释放资源
超时机制为每个事务设定超时时间,超时后自动终止并释放资源