在互联网大并发应用大行其道的今天,应用的开发总是离不开锁,在分布式应用中,最常见的莫过于基于数据库的行级锁了,由于互联网公司中比较主流的数据库还是mysql,所以这一话题绕不开的就是mysql了,但是由于mysql中innoDb引擎特殊的机制,经常一不小心就会发生死锁,本次咱们就来聊一聊基于mysql innodb 实现的行级锁,以及为什么会产生死锁,和如何避免死锁

首先,使用mysql实现行级锁的两大前提就是,innodb引擎并且开启事务。由于MySQL/InnoDB的加锁分析,一直是一个比较困难的话题。本次咱们暂时只讨论在日常应用中 select .... from table where ..... for update 语句并且在 Repeatable Read 事务隔离级别下

在此之前先明确几个概念:

1.Index Key:

用于确定SQL查询在索引中的连续范围(起始范围+结束范围)的查询条件,被称之为Index Key。

2.Index Filter:

在完成Index Key的提取之后,我们根据where条件固定了索引的查询范围,但是此范围中的项,并不都是满足查询条件的项。根据其他条件排除此范围中不满足的项

3.Table Filter:

所有不属于索引列的查询条件,均归为Table Filter之中。

一个sql的筛选过程就是先Index Key 到 Index Filter 再到 Table Filter。

其实死锁最大的难点可能就是很多人不知道一条for update到底是怎么加锁的,而在innodb引擎中行级锁分为以下三种锁

1.Record Lock

单个行记录上的锁

2.Gap Lock

间隙锁,锁定一个范围,不包括记录本身

3.Next-Key Lock

锁定一个范围和记录本身

我们分以下举例说明:

select * from table where id = 1 for update;

id 是主键的时候,本条sql在Index Key阶段可以确定唯一一条数据,所以会在聚簇索引上加Record Lock

id 是普通索引的时候,本条sql在Index Key阶段筛选出的数据不具有唯一性,所以Innodb为了防止幻度,会加Gap Lock+Next-Key Lock(Repeatable Read 事务隔离级别下,在Table Filter阶段对相应的聚簇索引上加Record Lock

id 不是索引的时候,本条sql在Table Filter阶段进行全表扫描,会在所有的聚簇索引上加锁,相当于全表锁,这是由于MySQL的实现决定的。如果一个条件无法通过索引快速过滤,那么innodb引擎层面就会将所有记录对应的聚簇索引加锁后返回,然后由MySQL Server层进行过滤,在高版本的mysql中会将不符合的记录再解锁

select * from table where id = 1 and time = '2019-06-18' for update;

id 是主键,time不是索引的时候,本条sql在Index Key阶段可以确定唯一一条数据,Index Filter,Table Filter 都只有一条数据,所以会在聚簇索引上加Record Lock.

id 是普通索引,time不是索引的时候,本条sql在Index Key阶段筛选出的数据不具有唯一性,所以Innodb为了防止幻度,会加id和小于1的索引之间加Next-Key Lock锁,在大于id和下一个索引之间加和Gap Lock锁(Repeatable Read 事务隔离级别下),Table Filter阶段会扫描出id = 1 范围下所有的聚簇索引加锁

id 不是索引,time不是索引的时候,本条sql在Table Filter阶段进行全表扫描,会在所有的聚簇索引上加锁,相当于全表锁

id 和time都是普通索引的时候,会再id索引和time索引上分别加Next-Key Lock和Gap Lock,在Table Filter阶段对相应的聚簇索引上加Record Lock

由上两个例子得出,我们的for update 并不时都锁一条记录,也并不是只有一个锁,这两个例子基本上已经包含了for update中常见的锁,在此基础上我们可以根据MySQL的加锁规则,写出不会发生死锁的SQL,比如,只用聚簇索引做where条件,也可以根据MySQL的加锁规则,定位出线上产生死锁的原因。

你真的会用mysql行级锁吗?mysql 行级锁全解析的更多相关文章

  1. MySQL十种锁,一篇文章带你全解析

    MySQL有两个核心的知识点,索引和锁.前几篇文章已经详细讲解了MySQL索引实现机制,今天再一起学习一下MySQL的锁. 1 为什么要加锁? 当多个事务并发操作同一批数据的时候,如果不加锁,就无法保 ...

  2. Mysql的视图、存储过程、函数、索引全解析

    视图是查询命令结果构成的一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集合,并可以当作表来查询使用. 1创建视图 --格式:C ...

  3. MySQL学习笔记(五):MySQL表级锁和行级锁

    一:概述 相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制.比如,MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking ...

  4. mysql锁——innodb的行级锁

    [前言]数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则.MySQL数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎所针对的应 ...

  5. 极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间

    极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间极客时间 Mysql实战45讲 07讲行锁功过:怎么减少行锁对性能的影响笔记 极客时间 笔记体会: 方案一,事务相 ...

  6. mysql锁机制之行锁(四)

    前言 顾名思义,行锁就是一锁锁一行或者多行记录,mysql的行锁是基于索引加载的,所以行锁是要加在索引响应的行上,即命中索引,如下图所示: InnoDB 支持多粒度锁(multiple granula ...

  7. 【问答分享第一弹】MySQL锁总结:MySQL行锁、表锁、排他锁、共享锁的特点

    大家好,我是小于哥哈.前几天能分享了第一期面试题,MySQL 中有哪几种锁 和 这些锁各有哪些特点 ,这道面试题是经常会被问到的一个面试题,大家反馈的都挺不错的.今天特此来总结一下. 首发于公众号[终 ...

  8. MySQL 笔记整理(7) --行锁功能:怎么减少行锁对性能的影响?

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 7) --行锁功能:怎么减少行锁对性能的影响? MySQL的行锁是在引擎层由各个引擎自己实现的.因此,并不是所有的引擎都支持行锁,如 ...

  9. MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)

    悲观锁: 顾名思义,很悲观,就是每次拿数据的时候都认为别的线程会修改数据,所以在每次拿的时候都会给数据上锁.上锁之后,当别的线程想要拿数据时,就会阻塞,直到给数据上锁的线程将事务提交或者回滚.传统的关 ...

随机推荐

  1. python代码风格检查工具──pylint

    pylint是一个python代码检查工具,可以帮助python程序员方便地检查程序代码的语法和风格,通过这个工具,可以使你的python代码尽量保持完美,哈哈.具体可以检查什么东西呢?比如你写了 f ...

  2. Swagger 生成API文档

    1.打开程序包管理控制台输入: Install-Package Swashbuckle 2.打开App_Start文件夹下的SwaggerConfig.cs文件找到 c.IncludeXmlComme ...

  3. 极简代码(七)—— SNR

    10⋅log10∑x=1Nx∑y=1Nyf2(x,y)∑x=1Nx∑y=1Ny(f(x,y)−f^(x,y))2 这里不妨先用 matlab 所支持的函数对象(函数式编程)定义这样一个函数变量,可作为 ...

  4. shell脚本自动化安装LAMP

    #!/bin/bash#auto make install LAMP#by authors yehailun #arp和apr-util依赖APR_FILES=apr-1.6.2.tar.gz APR ...

  5. Entity种类(动态代理)

    动态代理:延迟加载+自动化修改跟踪满足条件     修改方式见修改EF设置eg.     测试     结果    

  6. MyBatis 模板

    mybatis-config.xml: <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE co ...

  7. 一个字体,大小,颜色可定义的自绘静态框控件-XColorStatic 类(比较好看,一共19篇自绘文章)

    翻译来源:https://www.codeproject.com/Articles/5242/XColorStatic-a-colorizing-static-control XColor Stati ...

  8. xcode缓存清理

    移除对旧设备的支持 影响:可重新生成:再连接旧设备调试时,会重新自动生成. 路径: ~/Library/Developer/Xcode/iOS DeviceSupport 如果你不是在wb145230 ...

  9. Delphi XE5 Android Dialogs 对话框(模拟做了一套)

    最近要在Android中使用对话框, 但发现无现成的, TOpenDialog等已经不支持移动设备,还好系统提供了一些文件目录函数可用,于是简单的模拟了一个,支持OpenDialog ,SaveDia ...

  10. TP5.0中使用trace调试

    1.在项目 的配置文件config.php 配置, 2.在程序中使用trace: 3.在浏览器网页上打开 得到如下图所示:点击 “用户变量”,即可查看使用trace输出的变量 或者我们使用 trace ...