1    背景    1

1.1    MVCC:Snapshot Read vs Current Read    2

1.2    Cluster Index:聚簇索引    3

1.3    2PL:Two-Phase Locking    3

1.4    Isolation Level    4

1.背景

MySQL/InnoDB的加锁分析,一直是一个比较困难的话题。我在工作过程中,经常会有同事咨询这方面的问题。同时,微博上也经常会收到 MySQL锁相关的私信,让我帮助解决一些死锁的问题。本文,准备就MySQL/InnoDB的加锁问题,展开较为深入的分析与讨论,主要是介绍一种思 路,运用此思路,拿到任何一条SQL语句,都能完整的分析出这条语句会加什么锁?会有什么样的使用风险?甚至是分析线上的一个死锁场景,了解死锁产生的原 因。

注:MySQL是一个支持插件式存储引擎的数据库系统。本文下面的所有介绍,都是基于InnoDB存储引擎,其他引擎的表现,会有较大的区别。

1.1  MVCC:Snapshot Read vs Current Read

MySQL InnoDB存储引擎,实现的是基于多版本的并发控制协议——MVCC (Multi-Version Concurrency Control) (注:与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control)。MVCC最大的好处,相信也是耳熟能详:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系 统的并发性能,这也是为什么现阶段,几乎所有的RDBMS,都支持了MVCC。

在MVCC并发控制中,读操作可以分成两类:快照读 (snapshot read)与当前读 (current read)。快照读,读取的是记录的可见版本 (有可能是历史版本),不用加锁。当前读,读取的是记录的最新版本,并且,当前读返回的记录,都会加上锁,保证其他事务不会再并发修改这条记录。

在一个支持MVCC并发控制的系统中,哪些读操作是快照读?哪些操作又是当前读呢?以MySQL InnoDB为例:

快照读:简单的select操作,属于快照读,不加锁。(当然,也有例外,下面会分析)

select * from table where ?;

当前读:特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。

select * from table where ? lock in share mode;

select * from table where ? for update;

insert into table values (…);

update table set ? where ?;

delete from table where ?;

所有以上的语句,都属于当前读,读取记录的最新版本。并且,读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加S锁 (共享锁)外,其他的操作,都加的是X锁 (排它锁)。

为什么将 插入/更新/删除 操作,都归为当前读?可以看看下面这个 更新 操作,在数据库中的执行流程:

从图中,可以看到,一个Update操作的具体流程。当Update SQL被发给MySQL后,MySQL Server会根据where条件,读取第一条满足条件的记录,然后InnoDB引擎会将第一条记录返回,并加锁 (current read)。待MySQL Server收到这条加锁的记录之后,会再发起一个Update请求,更新这条记录。一条记录操作完成,再读取下一条记录,直至没有满足条件的记录为止。 因此,Update操作内部,就包含了一个当前读。同理,Delete操作也一样。Insert操作会稍微有些不同,简单来说,就是Insert操作可能 会触发Unique Key的冲突检查,也会进行一个当前读。

注:根据上图的交互,针对一条当前读的SQL语句,InnoDB与MySQL Server的交互,是一条一条进行的,因此,加锁也是一条一条进行的。先对一条满足条件的记录加锁,返回给MySQL Server,做一些DML操作;然后在读取下一条加锁,直至读取完毕。

1.2  Cluster Index:聚簇索引

InnoDB存储引擎的数据组织方式,是聚簇索引表:完整的记录,存储在主键索引中,通过主键索引,就可以获取记录所有的列。关于聚簇索引表的组织方式,可以参考MySQL的官方文档:Clustered and Secondary Indexes 。本文假设读者对这个,已经有了一定的认识,就不再做具体的介绍。接下来的部分,主键索引/聚簇索引 两个名称,会有一些混用,望读者知晓。

1.3  2PL:Two-Phase Locking

传统RDBMS加锁的一个原则,就是2PL (二阶段锁):Two-Phase Locking。相对而言,2PL比较容易理解,说的是锁操作分为两个阶段:加锁阶段与解锁阶段,并且保证加锁阶段与解锁阶段不相交。下面,仍旧以MySQL为例,来简单看看2PL在MySQL中的实现。

从上图可以看出,2PL就是将加锁/解锁分为两个完全不相交的阶段。加锁阶段:只加锁,不放锁。解锁阶段:只放锁,不加锁。

1.4  Isolation Level

隔离级别:Isolation Level, 也是RDBMS的一个关键特性。相信对数据库有所了解的朋友,对于4种隔离级别:Read Uncommited,Read Committed,Repeatable Read,Serializable,都有了深入的认识。本文不打算讨论数据库理论中,是如何定义这4种隔离级别的含义的,而是跟大家介绍一下 MySQL/InnoDB是如何定义这4种隔离级别的。

MySQL/InnoDB定义的4种隔离级别:

Read Uncommited

可以读取未提交记录。此隔离级别,不会使用,忽略。

Read Committed (RC)

快照读忽略,本文不考虑。

针对当前读,RC隔离级别保证对读取到的记录加锁 (记录锁),存在幻读现象。

Repeatable Read (RR)

快照读忽略,本文不考虑。

针对当前读,RR隔离级别保证对读取到的记录加锁 (记录锁),同时保证对读取的范围加锁,新的满足查询条件的记录不能够插入 (间隙锁),不存在幻读现象。

Serializable

从MVCC并发控制退化为基于锁的并发控制。不区别快照读与当前读,所有的读操作均为当前读,读加读锁 (S锁),写加写锁 (X锁)。

Serializable隔离级别下,读写冲突,因此并发度急剧下降,在MySQL/InnoDB下不建议使用。

php如何对mysql加锁_MySQL 加锁处理分析(一)相关推荐

  1. mysql 联合主键 加锁_MySQL 加锁处理分析

    背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备 ...

  2. 如何判断mysql死锁_MySQL 死锁问题分析

    线上某服务时不时报出如下异常(大约一天二十多次):"Deadlock found when trying to get lock;". Oh, My God! 是死锁问题.尽管报错 ...

  3. mysql 插入加锁_Mysql加锁过程详解(9)-innodb下的记录锁,间隙锁,next-key锁

    你需要知道的 之前我们介绍了排他锁,其实innodb下的记录锁(也叫行锁),间隙锁,next-key锁统统属于排他锁. 行锁 记录锁其实很好理解,对表中的记录加锁,叫做记录锁,简称行锁. 生活中的间隙 ...

  4. mysql崩溃_mysql崩溃原因分析

    最近开发人员那边总说他们的程序连接一台指定服务器的时候出现闪断的现象,有连接失败的日志生成.于是就登陆到这台机器上探查个究竟,看了下mysql的错误日志,发现有mysql崩溃的现象,数据目录下面生成好 ...

  5. mysql 高并发加锁_Mysql高并发加锁事务处理

    MySQL 使用 SELECT - FOR UPDATE 做事务写入前的确认 以MySQL 的InnoDB 为例,预设的 Tansaction isolation level 为 REPEATABLE ...

  6. mysql 事务 查询 范围加锁_MySQL死锁系列-常见加锁场景分析

    本文我们就从原理走向实战,分析常见 SQL 语句的加锁场景.了解了这几种场景,相信小伙伴们也能举一反三,灵活地分析真实开发过程中遇到的加锁问题. 如下图所示,数据库的隔离等级,SQL 语句和当前数据库 ...

  7. linux mysql 释放x锁_MySQL 加锁处理分析-转载

    背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备 ...

  8. mysql 并发_MySQL的并发控制与加锁分析

    本文主要是针对MySQL/InnoDB的并发控制和加锁技术做一个比较深入的剖析,并且对其中涉及到的重要的概念,如多版本并发控制(MVCC),脏读(dirty read),幻读(phantom read ...

  9. 一条简单的更新语句,MySQL是如何加锁的?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:Java_老男孩 来源:https://urlify.cn/ ...

最新文章

  1. 如何区分惯性器件的零偏误差?
  2. AJAX(三)jQuery AJAX.post
  3. 【OpenGL】六、Visual Studio 2019 配置 GitHub ( 提取和拉取简介 | 拉取远程代码 )
  4. 2012-2013年下学期计划
  5. 回文字符串啊~---太搞了 少年 DXH
  6. 直接启动SDK Manager: $ADNROID_HOME/tools/android
  7. SpringBootAdmin项目创建
  8. java 线程简介_java多线程介绍
  9. Maven 在eclipse中如何配置
  10. SpringAOP 学习笔记
  11. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_05 IO字符流_1_字符输入流_Reader类FileRead...
  12. OpenCV 二值化
  13. 微信小程序短信倒计时60s功能
  14. 高德地图E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
  15. ios 图片简单360度旋转动画
  16. JWS实现WebService
  17. Python开发(基础):列表List
  18. 计算机二级Python真题(七)
  19. OCP学习——数据库整库备份恢复实验
  20. java 获取string值_java如何获取String里面的键值对:key=valuekey=value

热门文章

  1. GZOI2019GXOI2019 滚粗记
  2. php取网盘真实链接,利用蓝奏做个人小文件网盘和获取真实下载地址
  3. 阿里的Maven仓库地址
  4. 机房温度不够冷?可能是系统有问题!
  5. 修改注册表来解决Microsoft Office中word和excel表格打开新文件时前面最小化的文件重新弹出显示的问题
  6. Linux下的USB驱动
  7. app上线指南(中文版)
  8. java 外码 内码_什么是汉字的内码、外码、交换码、字形码?
  9. java文件后缀_java源文件名的后缀是什么?
  10. 知识图谱方向顶会小记