行锁

MySQL的行锁都是在引擎层实现的,但是 MyISAM 不支持行锁,意味着并发控制只能使用表锁,同一张表任何时刻只能被一个更新在执行,影响到业务并发度。InnoDB 是支持行锁的,这也是 MyISAM 被 InnoDB 替换的重要原因之一。

行锁就是针对数据库中表的行记录的锁,这很好理解,比如事务 A 更新了一行,而这时候,事务 B 也要更新一行,则必须等事务 A 的操作完成后才能更新。

两阶段锁

先举个例子,假设有一个表 t,主键是 id,其中一个字段是 k,在下面的操作中,事务 B 的 update 语句执行时,会是什么现象呢 ?说明:红色表示事务 A,黄色表示事务 B:

这个问题的结论取决于事务 A 执行完前两条语句后,持有哪些锁,以及在什么时候释放。

实际上,事务 A 持有两个记录的行锁,都是在 commit 的时候才释放的,所以事务 B 的 update 就会被阻塞,直到事务 A 执行 commit 之后,事务 B 才能被继续执行。也就是说,在 InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释放,需要等事务结束时才释放,这就是两阶段锁协议,分为加锁阶段和解锁阶段,所有的 lock 操作都在 unlock 操作之后。

假设你负责实现一个电影票在线交易业务,顾客 userA 要在影院 cinema 购买电影票,需要涉及以下操作:

扣除顾客 userA 账户余额

增加影院 cinema 账户余额

记录一条交易日志

也就是说,完成这次交易,需要 update 两条记录,并 insert 一条记录。当然为了保证交易的原子性,我们需要这三个操作放在一个事务中。与此同时,还有顾客 userB 也在影院购买电影票,那么你会怎样安排这三个语句在事务中的顺序呢?

首先发现冲突的部分是语句 2,就是两个事务都要给 cinema 的账户余额增加电影票价。根据两阶段协议,不论怎么安排语句,所有的操作需要的行锁都是在事务提交的时候才释放的,要想使行锁在事务中不会停留太长时间,最大程度的减少了事务之间的锁等待,应该把语句 2 放在最后面。如下图所示:

死锁

如下图所示,事务 A 在等待事务 B 释放 id = 2 的行锁,而事务 B 在等待 事务 A 释放 id = 1 的行锁,事务 A 和事务 B 在互相等待对方的资源释放,就是进入了死锁状态。

在并发系统中,不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程进入无限等待的状态,成为死锁。

当进入死锁状态时,有下列 2 种策略:

通过 innodb_lock_wait_timeout 来设置超时时间,InnoDB 中默认值是 50s,第一个被锁住的事务 A 等待超过 50s 才会超时退出,其他事务才能得以执行,对于在线服务来说,这个等待时间往往是无法接受的。如果设置太短 1s,可能有的事务只是简单的锁等待,就被退出了,会出现很多误伤。

通过设置 innodb_deadlock_detect = on,发起死锁检测,发现死锁之后主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。比如回滚事务 A,让事务 B 继续执行。

死锁检测

正常情况下使用第 2 种策略的,但是快速发现死锁并进行处理,也是有额外负担的。你可以想象一下这个发现死锁的过程:每当一个事务被锁的时候,就要看看他依赖的线程有没有被别人锁住,判断是否出现了循环等待,也就是死锁。

假设有 1000 个并发线程,都要同时更新同一行,第 1 个线程来的时候检测数是 0;第 2 个线程来的时候,需要检测【线程1】有没有被别人锁住;第 3 个线程来的时候,需要检测【线程1,线程2】有没有被其他线程锁住,以此类推,第 n 个线程来的时候,检测数是 n - 1,所以总的检测数是 0 + 1 + 2 + 3 + 。。。+ (n - 1) = n(n -1)/2,所以时间复杂度应该是 O(n²)。

也就是 1000 个并发线程同时操作同一行,那么死锁检测操作就是 100 万这个量级的,虽然最终检测的结果是没有死锁,但是这期间要消耗大量的 CPU 资源,就会看到 CPU 利用率很高,但是每秒却执行不了几个事务。

那么怎么处理这种热点行更新导致的性能问题呢?

如果你能确定这个业务一定不会出现死锁,可以临时把死锁关掉,这种操作带有一定风险,因为业务设计的时候一般不会把死锁当成一个严重错误,毕竟出现死锁了,就回滚,然后通过业务重试一般就没有问题了,这是业务无损的,而关掉死锁检测意味着可能出现大量超时,这是业务有损的。

控制并发度,比如同一行最多只有 10 个线程在更新,这样死锁检测的成本很低,一个直接的想法就是在客户端做并发控制。可是如果客户端有 600 个,即使每个客户端控制到只有 5 个线程,汇总到数据库服务端以后,峰值并发数也有可能达到 3000。因此这个并发控制要在服务端,比如引入中间件来实现,在进入引擎之前排队。

将一行改成逻辑上的多行来处理,比如影院的账户余额等于 10 行记录的值总和,这样每次给影院账户加金额的时候,随机选取其中一条记录来加,冲突概率变为原来的1/10,减少锁的等待个数,也就减少了死锁检测的 CPU 消耗。这个方案看上去是无损的,但是需要根据业务逻辑做详细设计。如果账户余额减少,比如退票,这个时候就要考虑当一部分行记录变为 0 的时候,代码要有特殊处理。

————————————————

版权声明:本文为CSDN博主「笙南」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_38118016/article/details/90271468

mysql二级封锁协议_MySQL 行锁、两阶段锁协议、死锁以及死锁检测相关推荐

  1. Mysql的两阶段锁协议

    问题引入 我们都知道事务的四大特性,ACID,原子性.一致性.隔离性.持久性.那么事务是如何实现这样的特性的呢?其中原子性通过redo.undo.binlog日志来实现:持久性通过mysql底层的刷磁 ...

  2. 详解PostgreSQL数据库中的两阶段锁

    点击上方"蓝字" 关注我们,享更多干货! 数据库中的对象是共享的,假如不同的用户同时修改某个对象,就会出现数据错乱,从而破坏数据库的数据一致性,违反事务的隔离性原则. 为了满足隔离 ...

  3. 【数据库技术】2PL(两阶段锁)下的死锁与饥饿处理手段

    事务处理-2PL下的死锁与饥饿 2PL--2阶段锁存在的问题 一.死锁与等待图 1. 死锁(Deadlock) 2. 等待图(Wait-for graph) 二.死锁的处理手段 1. 死锁预防 2. ...

  4. mysql一个事务多个log_MySQL的两阶段事务提交是否先写binlog再写redolog也可行?

    下面是目前的MySQL两阶段提交规则: 事务的两阶段提交 ​ MySQL为了兼容其他非事务引擎的复制,在server服务层引入了binlog,Binlog负责记录所有引擎中的修改操作,也因为如此,bi ...

  5. mysql 二级什么意思_MySQL二级等级考试归纳——PHP篇

    终于到最后一篇了--累死宝宝了-- 基于二级考试的书写的php部分,不会太深,大概就是归纳一下书上有的内容,详细的PHP就科科 之前没接触过PHP,网上好多好教程,真后悔赶时间没去看那些教程直接跟着书 ...

  6. mysql 中有没有临时表_MySQL 中的两种临时表

    来源:阿里云RDS - 数据库内核组 链接:http://mysql.taobao.org/monthly/2016/06/07/ 外部临时表 通过CREATE TEMPORARY TABLE 创建的 ...

  7. mysql php 列转行_MySql行转列、列转行

    现mysql中有一张表php_user表,表结构为: 表中数据有: 现在想查询出来不同学生的语数外成绩在一行显示,那么需要用到行转列的用法, 一.行转列 1.使用case...when....then ...

  8. mysql 二级什么意思_MySQL二级等级考试归纳——概念篇

    准备考计算机二级了,归纳以复习,归纳下也方便自己以后看~也希望能对其他看这篇东东的人有帮助啦~ 打字快但是又渣,可能会有打错 按书本的章节归纳一遍,好像内容好多,分开概念篇和指令篇吧,以后会一边复习过 ...

  9. Mysql判断工作日函数_MySQL函数查找两个日期之间的工作日数

    慕田峪9158850 该解决方案使用与Rodger基本相同的方法,除了生成矩阵的方法要复杂得多.注意:此解决方案的此输出与NETWORKDAYS不兼容.与Rodger的解决方案一样,这可以计算开始日期 ...

最新文章

  1. jQuery简单实现iframe的高度根据页面内容自适应的方法(转)
  2. 简单文件的上传与保存
  3. zookeeper安装笔记
  4. python输出重定向到窗口_[python]重定向输出
  5. RecyclerView万能分割线
  6. python基础编码规范_Python语言的基本语法和编码规范.doc
  7. 全国计算机二级ms2017,2017全国计算机二级MS-Office选择题题库大全
  8. 科蒂斯控制器故障代码_卡特挖掘机故障代码【收藏备用】
  9. Servlet—简单的管理系统
  10. 通用 字符串工具类
  11. Linux chmod 修改多个文件权限
  12. matlab太阳影子定位,基于MATLAB软件的太阳影子定位
  13. 先爆火再遇冷 元宇宙能否托起梦想?
  14. 一文带你弄懂 CDN 技术的原理
  15. STM8L052低功耗模式
  16. python非法的标识符_Python标识符
  17. mysql的填充因子_数据库索引中的填充因子
  18. ccf认证--201809-1 卖菜(100分)
  19. 数据库 schema含义
  20. 生命周期模型_建立从思想到价值的生命周期模型

热门文章

  1. SAP Spartacus 如何重定义登录 Login Component
  2. OAuth 2.0 协议学习笔记
  3. Angular 依赖注入里factory函数的调用时机
  4. Angular Component的默认changeDetection策略
  5. SAP Spartacus layout设计原理
  6. 各种Java实现的常用排序算法
  7. how Kyma connection is established for the first time
  8. SAP CRM Fiori note header
  9. 一个关于微服务架构和monolithic架构的讨论
  10. IBASE structure