想要用好 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);

事物二阻塞

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

  1. 收集关于MySQL数据库的相关知识_关于Mysql数据库的知识总结

    2017年6月8日,天气阴.心情晴. 连续做梦两个晚上了,昨晚竟然梦见一个很长时间不联系的初中同学了,早上上班的路上聊了聊.女孩现在出差在贵州,风景秀美的地方.我说"你现在生活很滋润&quo ...

  2. MySQL数据库实用教程考核_《MySQL数据库实用教程》郑明秋,蒙连超,赵海侠【pdf】...

    内容简介 郑明秋.蒙连超.赵海侠主编的<MySQL数据库实用教程>是作者在多年的数据库开发实践与教学经验的基础上,根据计算机相关专业的职业岗位能力需求及学生的认知规律倾心组织编写的.本教材 ...

  3. MySQL数据库test连接语句_【MySQL数据库开发之二】MySQL 基础语句的书写与操作!...

    本篇Himi简单介绍一些MySQL数据库的基础操作: 注:mysql 语句对大小写不敏感,语句以分号";"标识语句结束: 1.   首先使用两个简单的查询语句: 查询当前版本:se ...

  4. mysql 数据库还原 不齐_请教mysql数据库还原问题。

    你的位置: 问答吧 -> 数据库 -> 问题详情 请教mysql数据库还原问题. 50多m,能不能拆分?上传到服务器上总是超时.怎么办? [ 本帖最后由 geniux 于 2007-9-2 ...

  5. mysql数据库密码为空_注意MySQL数据库用户root密码为空

    注意MySQL数据库用户root密码为空 文章作者:网友投稿 发布时间:2008-08-14 19:11:51 来源:网络 看到这大家肯定知道了,就是利用mysql输出一个可执行的文件而已.为什么不用 ...

  6. mysql数据库开启远程连接_安装MySQL数据库并开启远程访问

    一.安装MySQL数据库 MySQL安装在系统盘下(C:\Program Files),方便系统备份. 1.双击安装程序,勾选"I accept the license terms" ...

  7. mysql数据库更改文档_更改MySQL数据库目录位置

    更改MySQL数据库目录位置 MySQL默认的数据文档存储目录为/var/lib/mysql.假如要把MySQL目录移到/home/data下需要进行下面几步: 1.home目录下建立data目录 c ...

  8. mysql数据库后台命令备份_使用MySQL命令行备份及恢复数据库

    使用MySQL命令行备份及恢复数据库 下文对使用MySQL命令行备份及恢复数据库的方法及步骤进行了详细的介绍,如果您对MySQL命令行方面感兴趣的话,不妨一看. AD: 使用MySQL命令行,可以实现 ...

  9. mysql数据库约束详解_基于MySQL数据库的数据约束实例及五种完整性约束介绍

    为了防止不符合规范的数据进入数据库,在用户对数据进行插入.修改.删除等操作时,DBMS自动按照一定的约束条件对数据进行监测,使不符合规范的数据不能进入数据库,以确保数据库中存储的数据正确.有效.相容. ...

  10. mysql数据库密码为空_注意MySQL 数据库用户root密码为空_MySQL

    这篇文章着重介绍了MySQL数据库用户root密码为空的另类攻击方法,更多内容请参考下文: 1.连接到对方mysql 服务器 mysql -u root -h 192.168.0.1 mysql.ex ...

最新文章

  1. 在串口通信开发中实现自动查找串口端口的方法
  2. 编写并运行windows服务
  3. 如何查看、备份电脑隐藏的恢复分区
  4. java线程安全例子_Java总结篇系列:Java多线程(三)
  5. 伏安特性曲线实验报告_【鼎阳硬件智库原创 | 测试测量】动手测量电解电容器的阻抗频率特性...
  6. 内存池的设计和实现总结(一)
  7. iphone iPhone开发中如何将制作图片放大缩小代码实现案例
  8. Android shell命令查询ip,网关,DNS
  9. Xshell 一款很养眼的配色方案推荐
  10. Python classmethod()
  11. 万能打印之Delphi 2010实现(序言)
  12. 深鸿会深大小组学习笔记:第一周,从零开发鸿蒙小游戏2048app(上)
  13. 怎么看外文文献的影响因子_如何查询外文期刊的影响因子?
  14. Alize和NIST中sphere2.7编译问题
  15. Java 编程练习之:101-200之间的素数
  16. Python 爬虫学习笔记三:多页内容爬取内容分析及格式化
  17. 泱泱大中华,美丽我的家 - 俗晒网速,感受幸福
  18. Android Beacon开发
  19. 微信成语接龙小程序|微擎框架|带流量主|前端+后端完整源码
  20. JSOI2008 小店购物

热门文章

  1. 阿里云ESC服务器数据快速转移至轻量应用服务器
  2. 发纸牌c语言指针,算了算学了有一个月c语言了,写了个扑克牌程序
  3. oracle11gasm,oracle11gASM管理
  4. uoni扫地机器人好用吗_扫地机器人好用吗?了解性能看这篇
  5. oracle仲裁磁盘是一块磁盘吗,基于ASM冗余设计的架构,仲裁磁盘组应该如何去规划?...
  6. ConcurrentHashMap底层原理?
  7. 芝麻信用综合评估未通过,请选择商户支持的其他方式使用服务
  8. Android 底部上拉抽屉view
  9. Android 循环滚动控件ViewFlipper,可实现跑马灯或轮播图效果
  10. 中南大学王斌计算机学院,中南大学 信息科学与工程学院,长沙 410083