mysql数据库的各种锁_关于MySQL各类锁的总结

想要用好 MySQL,索引与锁是一个绕不开的话题。最近一直在维护以前的业务系统,线上频繁报出数据库死锁的异常警告,为了排查以及规避死锁的问题,因此对 MySQL 的锁(Innodb引擎)做了一个比较深入学习,顺便加深自己对 MySQL 的理解程度。个人感觉 MySQL 中的锁还是非常的杂,官网对于锁的介绍也是和盘托出,并没有分门别类的罗列出来,下面分别从锁的模式与算法来分析。

锁的模式

MySQL 中有锁的模式这个概念,在 Innodb 中锁的模式有共享锁(S锁)、排它锁(X锁)两大类。除了这两大类,还有一个意向锁的概念,意向锁在锁模式中有意向共享锁(IS锁)、意向排它锁(IX锁)两类。

共享锁(行级别)

共享锁也叫读锁,对于同一个资源,大家都可以同时加上共享锁,可以理解成非独家的资源,大家都可以获取。共享锁与排它锁互斥,在 MySQL 中可以使用“lock in share mode”语法显式的加共享锁。

1select * from test where id = 1 lock in share mode;

排它锁(行级别)

排它锁也叫写锁,排它锁不仅与共享锁互斥,排它锁与排它锁也互斥,在 MySQL 中可以使用“for update”语法显示的加排它锁。

1select * from test where id = 1 for update;

意向锁(表级别)

InnoDB 存储引擎支持多粒度锁定,当数据库对行记录进行加锁时,首先会在粗粒度的表级别加上意向锁。意向锁的主要目的是为了提升表锁的加锁效率,假设没有意向锁,数据库在对表进行加锁时,需要扫描表中所有的记录,查看是否有行锁与当前要加的表锁冲突。意向锁之间是没有冲突的,意向锁与普通的表锁之间有冲突。

意向共享锁

意向共享锁无法通过语法显式的操作,当加上行级别的共享锁时,意向共享锁就会存在,意向共享锁与排它锁(表级)冲突。

意向排它锁

意向排它锁与上面的意向共享锁类似,它与共享锁(表级)、排它锁(表级)都冲突。

普通锁(表级别)

表级别的锁因为粒度更粗,所以在判断是否有冲突时不仅要考虑表级别下的其它锁,还要考虑表中的行锁。

共享锁

除了对行可以加共享锁,也可以对表加共享锁,通过“lock table read”语法来对表加共享锁。表级别的共享锁不仅与表级别的排它锁冲突,而且与行级别的排它锁冲突。

1lock table test read;

排它锁

除了对行可以加排它锁,也可以对表加排它锁,通过“lock table write”语法来对表加共享锁。表级别的排它锁不仅与表级别的共享锁、排它锁冲突,而且与行级别的排它锁也冲突。

1lock table test write;

锁的算法

锁的模式侧重锁的意图,锁的算法更加偏重锁的范围,例如下面列举的这些锁都是跟锁住的范围区间有关系。为了更好的演示锁住的区间,下面给出测试的表结构以及数据方便论证。

表结构:

1

2

3

4

5

6

7

8CREATE TABLE `test_info` (

`id` int(11) NOT NULL,

`no` int(20) NOT NULL AUTO_INCREMENT,

`description` varchar(255) NOT NULL,

PRIMARY KEY (`id`),

UNIQUE KEY `idx_no` (`no`) USING BTREE,

KEY `idx_description` (`description`(191)) USING BTREE

);

数据:

1

2

3

4

5INSERT INTO `test_info`(`id`, `no`, `description`) VALUES (1, 10, '100');

INSERT INTO `test_info`(`id`, `no`, `description`) VALUES (2, 20, '200');

INSERT INTO `test_info`(`id`, `no`, `description`) VALUES (5, 50, '500');

INSERT INTO `test_info`(`id`, `no`, `description`) VALUES (10, 100, '1000');

INSERT INTO `test_info`(`id`, `no`, `description`) VALUES (11, 110, '1000');

记录锁

记录锁作用在精确匹配的唯一索引上,它与间隙锁最大的差别在于间隙锁锁住的是不存在的区间。

记录锁 SQL 示例:

主键索引加锁

事物一:

1select * from test_info where id = 1 for update;

事物二:

1select * from test_info where id = 1 for update;

事物二阻塞。

唯一索引加锁

事物一:

1select * from test_info where no = 10 for update;

事物二:

1select * from test_info where no = 10 for update;

事物二阻塞

普通索引加锁

事物一:

1select * from test_info where description = 1000 for update;

事物二:

1select * from test_info where id = 10 for update;

事物二阻塞,结束事物二,执行事物三

事物三:

1select * from test_info where id = 11 for update;

事物三阻塞,结束事物三,执行事物四

事物四:

1select * from test_info where id = 5 for update;

事物四未被阻塞。

普通索引作为二级索引被加锁时,对应的主键索引也是会被加锁的,所以可以看到 id 为 10、11 的记录都会被阻塞住。

间隙锁

间隙锁一般存在于 RR 的隔离级别,MySQL 在 RR 隔离级别下可以解决部分幻读的问题,依靠的就是间隙锁。间隙锁的上界、下界都是开区间,间隙锁存在的目的主要是为了阻塞插入操作,这样就不会存在相同的条件下查询的结果集不一致的情况。

间隙锁示例(RR隔离级别):

普通索引加锁(未命中记录)

事物一:

1select * from test_info where description = 300 for update;

事物二:

1INSERT INTO `test_info`(`id`, `no`, `description`) VALUES (3, 21, '210');

事物二会阻塞,因为示例中的事物隔离级别为 RR,并且在事物一中没有查询到记录,为了避免幻读发生,所以将 (200,500) 的期间锁住了。上面的介绍中有提到间隙锁一般存在于 RR 的隔离级别中,所以上面的示例在 RC 隔离级别下执行事物二是不会被阻塞的。

普通索引加锁(命中记录)

事物一:

1select * from test_info where description = 200 for update;

事物二:

1select * from test_info where description = 210 for update;

事物二阻塞,结束事物二,执行事物三

事物三:

1select * from test_info where description = 190 for update;

事物三阻塞。

如果普通索引命中了记录,那么被锁定的区间不仅有 (200,500),还有 (100,200],所以普通索引的前后都会被锁住。

唯一索引加锁

对于唯一索引如果命中记录,那么会加上记录锁(临间锁退化为记录锁,记录锁已演示这种场景),如果没有命中记录则会加上间隙锁。

事物一:

1select * from test_info where no = 21 for update;

事物二:

1INSERT INTO `test_info`(`id`, `no`, `description`) VALUES (3, 22, '210');

事物二阻塞

临键锁

临键锁是由记录锁与间隙锁组成的(区间为左开右闭),所以记录锁与间隙锁可以理解成特殊场景下的临键锁。Innodb 引擎行锁默认采用的就是临键锁的算法,只是在不同的场景下会退化成记录锁或者间隙锁。

特殊场景的锁

插入操作

插入操作加锁的操作是一个复杂的过程,并不会只存在一把锁。插入过程中首先会加插入意向锁,接着检查是否有唯一键冲突的问题,针对唯一性冲突还有可能会加上 S GAP(RC的隔离级别也会存在),当记录插入成功时还会对该条记录加上 X 的记录锁。

事物一:

1

2

3delete from test_info where no = 50;

insert into `test_info`(`id`, `no`, `description`) values (5, 50, 500);

事物二:

1insert into `test_info`(`id`, `no`, `description`) values (3, 30, 300);

事物二阻塞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/427803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

581. Shortest Unsorted Continuous Subarray连续数组中的递增异常情况

[抄题]: Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too. You need to find the shortest suc…

python enumerate函数返回值_python中enumerate函数用法实例分析

本文实例讲述了python中enumerate函数用法。分享给大家供大家参考。具体分析如下:今日发现一个新函数 enumerate 。一般情况下对一个列表或数组既要遍历索引又要遍历元素时,会这样写: for i in range (0,len(list)):print i ,list[i]但是这种…

Java异常处理原则与技巧总结

一 处理原则 Java异常代码中我们使用异常的目的是让异常的异常类型来提示“什么”被抛出了--- 即出了什么问题;用异常的栈打印信息来跟踪异常在“哪里”抛出 --- 即哪里出了问题; 异常提示信息来提示“为什么”会抛出 --- 即出问题的原因。在对异常进行…

python三阶魔方_三阶魔方自动求解及动态可视化matlab代码

三阶魔方自动求解及动态可视化matlab代码思路与步骤三阶魔方有6个面,每个面有333\times333小块,用一个6336\times3\times3633的矩阵来保存魔方的状态;定义412种魔方旋转行为:整体旋转(左右上下共4种方式AaCc),侧面(6个…

Qt 常用类——QStandardItemModel

转载:落叶知秋时 类QabstractItemModel,QabstractListModel,QAbstractTableModel不保存数据,用户需要从这些类派生出子类,并在子类中定义某种数据结构来保存数据。 与此不同,类QStandardItemModel负责保存数…

thinkphp mysql 中文_耗时5天解决thinkphp连接mysql中文乱码的问题

坑大,或者不大,它就在那里,等着你进。先前修改成熟的一个基于thinkphp3.1.2的后台框架,里面有我的autoCode,本来在新项目上不想再用这么落后的版本,但考虑到后台项目不对外使用,重点是autoCode是…

bzoj3203: [Sdoi2013]保护出题人

我三分这么好吗居然1A啦???提交的时候只是想着先WA一次的。。。。 这题真的很妙啊 首先第一步,就是把僵尸的生命值取一个前缀和,这样造成伤害的时候,可以视为同时对所有僵尸造成伤害。 那么就可以得到一个柿…

ad19原理图标注_AD19中原理图的模板如何进行编辑?

我们在进行原理图设计的时候,有时候不想去用软件自带默认的模板,想要用自己设计的模板,就涉及到我们的模板怎么去编辑的呢?我们应该如何去编辑原理图自己设计的模板?操作步骤是怎么的呢?我们今天就以AD19为…

mysql+秘密_mysql不被人知的秘密

http://blog.csdn.net/yueguanghaidao/article/details/69333872011先建立两张表。1.student表2.grade表一:mysql的复制技术1.表与数据的复制->>实现表结构和数据的同步create table desttable select * from srctable;(desttable:目标表,srctable…

项目管理中风险评价的必要性

摘要:在项目管理实践中,风险是时时存在的。 因此,如何评价、度量风险的大小,确定可接受风险和不可接受风险,对不可接受风险作进一步分析,制定补偿措施,将风险减至最小或可以接受的水平&#xff…

mysql一个表几亿数据_如何在mysql 造1亿条记录的大容量数据表?

背景及目标:现有数据1000w单表,为压力测试准备1亿条数据。步骤:1.将1000w条记录,除id外都导入到多个文件中://DELIMITERDROP PROCEDURE if EXISTS createManyTable;create PROCEDURE createManyTable()BEGINDECLARE i …

windows键盘在mac上怎么识别_Mac电脑怎么使用pc键盘?

苹果电脑一般需要使用配套的mac键盘,毕竟按键和普通pc键盘不一样。但是总会遇到一些情况,比如配套的mac键盘坏了,而刚好有一个pc键盘,那么这时候苹果电脑要怎么用pc键盘呢?这边小编跟大家介绍mac电脑连接pc键盘以及设置…

LOJ#6002. 「网络流 24 题」最小路径覆盖

模板。 1 #include<iostream>2 #include<cstring>3 #include<cstdio>4 //#include<time.h>5 //#include<complex>6 //#include<set>7 //#include<queue>8 #include<algorithm>9 #include<stdlib.h>10 using namespace s…

zabbix mysql设置中文乱码_解决zabbix监控因php问题导致图形界面中文乱码方法

解决因编译php中添加了-enable-gd-jis-conv选项导致Zabbix监控系统图形界面中文乱码问题现象&#xff1a;php编译参数&#xff1a;说明&#xff1a;如果PHP编译时启用–enable-gd-jis-conv选项的话&#xff0c;那么非ASCII字符(例如汉字、拼音、希腊文和箭头) 会被当成EUC-JP编…

熟悉常用的HDFS操作

一、Hadoop提供的Shell命令完成相同任务&#xff1a; 在本地Linux文件系统的“/home/hadoop/”目录下创建一个文件txt&#xff0c;里面可以随意输入一些单词.在本地查看文件位置&#xff08;ls&#xff09;在本地显示文件内容使用命令把本地文件系统中的“txt”上传到HDFS中的当…

mysql 低端_mysql入门

相关了解(重点内容从标题一开始)目前主流数据库有:sqlserver, mysql, Qracle, SQLite, Access, MS SQL Server等, 我主要说的是mysql;以下几点需要记住!!!SQL包括了所有对数据库的操作, 主要由4个部分组1. 数据库定义语言(DDL): 用于定义和管理数据库对象, 包括数据库, 基本表,…

阿里云服务器由于被检测到对外攻击,已阻断该服务器对其它服务器端口的访问...

问题&#xff1a; (系统&#xff1a;CentOS 7.2 ) 前几天在阿里云服务器安装了Redis, 刚开始没有设置redis密码, 后台阿里云发送多次邮件提示如下&#xff1a; 经过几次波折才发现并彻底解决了问题&#xff1a; 原因&#xff1a; 估计是因为 Redis服务开启时没有设置密码 &…

opencv rect画旋转矩形_在opencv c中绘制旋转的矩形

既然你想要一个填充的矩形,你应该使用fillConvexPoly&#xff1a;// Include center point of your rectangle, size of your rectangle and the degrees of rotationvoid DrawRotatedRectangle(cv::Mat& image, cv::Point centerPoint, cv::Size rectangleSize, double ro…

批量找注入 python3+sqlmap结合

注入一直都是用sqlmap 导致本来就不怎么精通的手工注入现在就忘的一干二净 想实战练习 却一时又找不到有注入的网站 于是便有了这篇文章 想找个批量获取域名链接的工具 但都是只是获取域名而已 都没获取后面的参数 于是自己写了个只获取bing前10页的结果 输入q 结束循环…

python collections模块_Python 的collections模块

前言&#xff1a;collections是实现了特定目标的容器&#xff0c;以提供python标准内建容器dict,list,set和tuple的替代选择。CounterCounter是一个dict子类&#xff0c;主要是用来对你访问的对象的频率进行计数import collections#统计字符出现的次数test1 collections.Count…