在互联网大并发应用大行其道的今天,应用的开发总是离不开锁,在分布式应用中,最常见的莫过于基于数据库的行级锁了,由于互联网公司中比较主流的数据库还是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. Notepad++ 自定义关键字

    Notepad++是一款輕便好用的編輯器,但可能有些語言的關鍵字不全,比方SQL中,默認關鍵字沒有Merge. 怎样給Notepad++中的語言添加關鍵字,而不是大動干戈自定義一個語言? 步驟: Se ...

  2. Matlab随笔之矩阵入门知识

    原文:Matlab随笔之矩阵入门知识 直接输入法创建矩阵 – 矩阵的所有元素必须放在方括号“[ ]”内: – 矩阵列元素之间必须用逗号“,”或空格隔开,每行必须用“;”隔开 – 矩阵元素可以是任何不含 ...

  3. mac 端安装JAVA开发环境

    一.maven安装 下载地址   https://maven.apache.org/download.cgi 下载 apache-maven-3.5.2-bin-zip 将下载的文件放在某路径下 修改 ...

  4. windows常用cmd指令

    打开命令行 1.在菜单栏中搜索命令行 2.在文件管理器的Path栏输入cmd,则在当前目录打开命令行 3.Windows+R,输入cmd,回车 ping(网络诊断工具) ping是Windows.Un ...

  5. jquery mobile 笔记

    1.navbar 相关 <nav data-role="navbar">    <ul>      <li><a href="# ...

  6. MultiBinding

    <StackPanel> <Slider x:Name="sl1" Minimum="10" Maximum="100"/ ...

  7. jquery表单过滤器

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  8. 将自定义控件加载到RichTextbox并进行交互

    先前遇到一个问题,将自定义控件加载到RichTextbox后,无法触发自定义控件的各种事件,最终找到解决办法:设置RichTextbox的IsDocumentEnabled="True&qu ...

  9. Image Caption论文合辑2

    说明: 这个合辑里面的论文不全是Image Caption, 但大多和Image Caption相关, 同时还有一些Workshop论文. Guiding Long-Short Term Memory ...

  10. Python标准库(3.x): 内建函数扫盲

    Built-in Functions abs() dict() help() min() setattr() all() dir() hex() next() slice() any() divmod ...