此篇博客是【眼见为实】系列的第一篇博客,主要从理论上讲了数据库并发可能会出现的问题,解决并发问题的技术——封锁,封锁约定的规则——封锁协议。然后简单说明了数据库事务隔离级别和封锁协议的对应关系。后面的几篇博客都是通过亲身实践探究InnoDB引擎在各个隔离级别下的实现细节。

数据库并发的几大类问题

①丢失修改(Lost Update)

两个事务T1和T2同时读入同一数据并修改,T2的提交的结果破坏了T1提交的结果,导致T1的修改被丢失(第二类丢失更新)。

还有一种特殊的丢失修改(第一类丢失更新),如下图。因为这种丢失修改在【READ UNCOMMITED】隔离级别下都不会出现,所以不进行讨论。

②不可重复读(Non-Repeatable Read)

事务T1读取数据后,事务T2执行更新操作,使事务T1无法再现前一次读取结果。

具体包括三种情况:

(1)事务T1读取某一数据后,事务T2对其做了修改,当事务T1再次读取该数据时,得到与前一次不同的值。

(2)事务T1按照一定条件读取了某些数据记录后,事务T2删掉了其中部分记录,当T1再次按相同条件查询数据时,发现某些记录消失了。

(3)事务T1按照一定条件读取了某些数据记录后,事务T2插入了一些记录,当T1再次按相同条件查询数据时,发现多了一些记录。

③幻读(Phantom Read)

幻读其实是不可重复读的一种特殊情况。不可重复读(2)和(3)也称为幻读现象。不可重复读是对数据的修改更新产生的;而幻读是插入或删除数据产生的。

④读脏数据(Dirty Read)

事务T1修改某一数据,并将其写回磁盘,事务T2读取同一数据后,T1因为某些原因回滚,这时T1修改过的数据恢复原值,T2读取到的数据就与数据库中的数据不一致,则T2读取到数据就为“脏数据“,即不正确的数据。

并发控制的主要技术是封锁

基本封锁类型:

①排它锁(Exclusive Locks,简称X锁)

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

②共享锁(Share Locks,简称S锁)

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

排它锁与共享锁的相容矩阵

封锁协议

在运用X锁和S锁这两种基本封锁,对数据对象加锁时,还需要约定一些规则。例如何时申请X锁和S锁,持锁时间,何时释放等。这些规格称为封锁协议。

一级封锁协议

一级封锁协议:事务T在修改数据A之前必须对其加X锁,直到事务结束才释放。事务结束包括正常结束(Commit)和非正常结束(RollBack)。

一级封锁协议可防止丢失修改。

使用一级封锁协议解决了图1中的覆盖丢失问题。事务T1在读A进行修改之前先对A加X锁,当T2再请求对A加X锁时被拒绝,T2只能等待T1释放A上的锁后T2获得A上的X锁,这时它读取的A已经是T1修改后的15,再按照此值进行计算,将结果值A=14写入磁盘。这样就避免了丢失T1的更新。

二级封锁协议

二级封锁协议:一级封锁协议加上事务T在读取数据A之前必须先对其加S锁,读完后即可释放S锁。

二级封锁协议除防止了丢失修改,还进一步防止了读“脏”数据。

使用二级封锁协议解决了图2中的脏读问题。事务T1在读C进行修改之前先对C加X锁,修改其值后写回磁盘。这时T2请求在C上加S锁,因为T1在C上已经加了X锁,所以T2只能等待。T1因为某种原因被撤销,C恢复原值100。T1释放C上的X锁后T2获得C上的S锁,读C=100。这样就避免了读“脏”数据。

三级封锁协议

三级封锁协议:一级封锁协议加上事务T在读取数据A之前必须先对其加S锁,直到事务结束才释放。

三级封锁协议除防止了丢失修改和读“脏”数据,还进一步防止了不可重复读。

使用三级封锁协议解决了图3中的不可重复读问题。事务T1在读取数据A和数据B之前对其加S锁,其他事务只能再对A、B加S锁,不能加X锁,这样其他事务只能读取A、B,而不能更改A、B。这时T2请求在B上加X锁,因为T1已经在B上加了S锁,所以T2只能等待。T1为了验算结果再次读取A、B的值,因为其他事务无法修改A、B的值,所以结果仍然为150,即可重复读。此时T1释放A、B上的S锁,T2才获得B上的X锁。这样就避免了不可重复读。

活锁和死锁

封锁可能会引起活锁活死锁。

活锁

如果事务T1封锁了数据R,事务T2又请求封锁数据R,于是T2等待。事务T3也请求封锁R,当事务T1释放了数据R上的封锁之后系统首先批准了事务T3的封锁请求,T2仍然等待。然后T4又申请封锁R,当T3释放了R的封锁之后系统又批准了T4的封锁请求。T2有可能一直等待下去,这就是活锁。

避免活锁的方法就是先来先服务的策略。当多个事务请求对同一数据对象封锁时,封锁子系统按照请求的先后对事务排队。数据对象上的锁一旦释放就批准申请队列中的第一个事务获得锁。

死锁

如果事务T1封锁了数据R1,事务T2封锁了数据R2,然后T1又请求封锁数据R2,因为T2已经封锁了数据R2,于是T1等待T2释放R2上的锁。接着T2又申请封锁R1,因为因为T1已经封锁了数据R1,T2也只能等待T1释放R1上的锁。这样就出现了T1在等待T2,T2也在等待T1的局面,T1和T2两个事务永远不能结束,形成死锁。

死锁的预防:

①一次封锁法

一次封锁法要求事务必须一次将所有要使用的数据全部加锁,否则不能继续执行。例如上图中的事务T1将数据R1和R2一次加锁,T1就能执行下去,而T2等待。T1执行完成之后释放R1,R2上的锁,T2继续执行。这样就不会产生死锁。

一次封锁法虽然能防止死锁的发生,但是缺点却很明显。一次性将以后要用到的数据加锁,势必扩大了封锁的范围,从而降低了系统的并发度。

②顺序封锁法

顺序封锁法是预先对数据对象规定一个封锁顺序,所有的事务都按照这个顺序实行封锁。

顺序封锁法虽然可以有效避免死锁,但是问题也很明显。第一,数据库系统封锁的数据对象极多,并且随着数据的插入、删除等操作不断变化,要维护这样的资源的封锁顺序非常困难,成本很高。第二,事务的封锁请求可以随着事务的执行动态的确定,因此很难按照规定的顺序实行封锁。

可见,预防死锁的产生并不是很适合数据库的特点,所以在解决死锁的问题上普遍采用的是诊断并且解除死锁。

死锁的诊断与解除:

①超时法

如果一个事务的等待时间超过了默认的时间,就认为是产生了死锁。

②等待图法

一旦检测到系统中存在死锁就要设法解除。通常的解决方法是选择一个处理死锁代价最小的事务,将其撤销,释放此事务持有的所有的锁,恢复其所执行的数据修改操作,使得其他事务得以运行下去。

两段锁协议

所谓的二段锁协议是指所有事务必须分两个阶段对数据进行加锁和解锁操作。

在对任何数据进行读、写操作之前,首先要申请并获得该数据的封锁。

在释放一个封锁之后,事务不在申请和获得其他封锁。

也就是说事务分为两个阶段。第一个阶段是获得封锁,也称为扩展阶段。在这个阶段,事务可以申请获得任何数据项任何类型的锁,但是不能释放任何锁。第二阶段是释放封锁,也称为收缩阶段。在这个阶段,事务可以释放任何数据项上任何类型的封锁,但是不能再申请任何锁。

事务遵守两段锁协议是可串行化调度的充分条件,而不是必要条件。也就是说遵守两段锁协议一定是可串行化调度的,而可串行化调度的不一定是遵守两段锁协议的。

左侧T1、T2遵循两段锁协议,右侧T1、T2并不遵循两段锁协议

两段锁协议和一次封锁法的异同

一次封锁法要求事务必须将要使用的数据全部加锁,否则不能继续执行。因此一次封锁法遵守两段锁协议。

但是两段锁协议并不要求事务将要使用的数据一次全部加锁,因此两段锁协议可能发生死锁。如图:

数据库隔离级别

封锁协议和隔离级别并不是严格对应的。

各种隔离级别所能避免的并发问题

本文为博主学习感悟总结,水平有限,如果不当,欢迎指正。

如果您认为还不错,不妨点击一下下方的[【推荐】](javascript:void(0)

mysql的封锁协议_【眼见为实】数据库并发问题 封锁协议 隔离级别相关推荐

  1. 【眼见为实】数据库并发问题 封锁协议 隔离级别

    目录 序 数据库并发的几大类问题 ①丢失修改(Lost Update) ②不可重复读(Non-Repeatable Read) ③幻读(Phantom Read) ④读脏数据(Dirty Read) ...

  2. mysql 数据库事务 (二)隔离级别

    属于事务四大特性之一的隔离性(isolation),解决两个并发事务同时访问数据库表相同的行时,可能存在的问题 目录 基础 四大隔离级别 隔离级别与一致性关系 如何设置 作用范围 补充: 额外: 第一 ...

  3. 数据库零碎要点001_数据库的4大特性(原子性_持久性_隔离性_一致性)_数据库的隔离级别(脏读_幻读_不可重复读)_mysql如何设置隔离级别

    本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务 ...

  4. 数据库并发问题和事务隔离界别

    数据库并发问题和事务隔离界别 一.数据库的并发问题 1. 脏读 2. 不可重复读 3. 幻读 二.事务隔离界别 1. Read Uncommited:读未提交的数据 2. Read Commit:读已 ...

  5. MySQL事务与锁详解,并发读异常与隔离策略

    文章目录 一.事务概念及ACID特性 二.隔离级别介绍 三.事务具体实现 3.1 undo log与redo log 3.2 MVCC 3.3 锁 3.3.1 粒度锁类型 3.2 锁算法介绍 四.并发 ...

  6. spring 事务隔离级别和传播行为_Java工程师面试1000题146-Spring数据库事务传播属性和隔离级别...

    146.简介一下Spring支持的数据库事务传播属性和隔离级别 介绍Spring所支持的事务和传播属性之前,我们先了解一下SpringBean的作用域,与此题无关,仅做一下简单记录. 在Spring中 ...

  7. 数据库 之 事务控制和隔离级别

    1  概述 事务是指一组原子性的SQL查询.或者是一个或多个SQL语句组成的独立工作单元:MyISAM不流行的原因很大是因为其不支持事务的处理功能. 2  事务日志 事务日志定义属性,有些参数可以运行 ...

  8. 数据库事务的四种隔离级别

    文章目录 1. 引言 2. 事务隔离级别 2.1 事务四种隔离级别 2.2 查看隔离级别 3. 脏读/幻读/不可重复读 3.1 脏读 3.2 不可重复读 3.3 幻读 4. 总结: 1. 引言 &qu ...

  9. 数据库事务的ACID及隔离级别

    文章目录 ACID 概念 四大特性 并发控制 隔离级别 串行化 可重复读 提交读 未提交读 默认隔离级别 读现象举例 脏读 不可重复读 幻读 隔离级别 VS 读现象 隔离级别 VS 锁持续时间 ACI ...

  10. sql相同顺序法和一次封锁法_【数据库】面试题汇总

    1.数据库中left join与right join,inner join,full join的区别 Paste_Image.png 2.关于索引: 索引的数据结构: B+树结构 Paste_Imag ...

最新文章

  1. redis集合数据过期_如何从Redis中的集合中自动删除过期的密钥?
  2. 帝国cms让当前栏目显示不同样式(图文)
  3. [UWP]了解IValueConverter
  4. Linux centos openshift安装教程整理
  5. nginx 压缩和缓存设置
  6. 一次性掌握JDK、JRE、JVM的概念以及三者之间的关系【2021整理】
  7. Tensorflow关于Dataset的一般操作
  8. Android 编程下的计时器
  9. java开发面试自我介绍模板_java应聘面试自我介绍范文
  10. 亲戚关系关系算法java程序_python版亲戚关系计算器
  11. jQueryphotoClip-图片上传并裁剪
  12. linux系统双显示器怎么设置复制,linux系统双显示器设置
  13. PLM与ERP的区别
  14. mapgis明码文件转为点线面文件_MapGIS明码文件的获得和在坐标转化中的应用研究(2)...
  15. 嵌入式(文件)数据库与数据库服务器的区别
  16. Access denied for user 'root'@'localhos
  17. 宝塔一键安装php,宝塔管理面板一键安装Tipask3.5版本教程
  18. 使用scrapy框架做武林中文网的爬虫
  19. CSS 1px边框问题两个解决方案
  20. 机器学习之recall、precision、accuracy

热门文章

  1. 2021年起重机械指挥考试题库及起重机械指挥最新解析
  2. 肯德基真的没有什么太多吃的谨慎洋…
  3. win2008 mysql 群集_win2003服务器下配置 MySQL 群集(Cluster)的方法 -电脑资料
  4. jQuery基本操作--制作论坛发帖
  5. Web大学生网页作业成品——个人班级网站设计与实现(HTML+CSS)
  6. 3dsmax2018可编辑多边形常用操作及部分快捷键
  7. 计算机IPv4升级到IPv6的技术,IPv4到IPv6的变化
  8. 《英语语法新思维初级教程》学习笔记(八)一般时态
  9. 计算机函数left的用法,excel的left函数的用法
  10. 计算机表格复制粘贴,表格之间无法复制粘贴怎么办_两个EXCEL表格为什么不能复制和粘贴-win7之家...