资讯专栏INFORMATION COLUMN

从源码分析 MySQL 死锁问题入门

JessYanCoding / 257人阅读

摘要:还没完但是为了效率考量,做了优化,对于不满足条件的记录,会在判断后放锁,最终持有的,是满足条件的记录上的锁,但是不满足条件的记录上的加锁放锁动作不会省略。

这篇文章主要讲的是如何通过调试 MySQL 源码,知道一条 SQL 真正会拿哪些锁,不再抓虾,瞎猜或者何登成大神没写过的场景就不知道如何处理了

通过好多个深夜艰难的单步调试,终于找到了一个理想的断点,可以看到大部分获取锁的过程

代码在lock0lock.cstatic enum db_err lock_rec_lock() 函数中,这个函数会显示,获取锁的过程,以及获取锁成功与否的情况

对于之前何登成大神博客里面的内容(hedengcheng.com/");

场景1:通过主键进行删除

表结构

CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT "", PRIMARY KEY (`id`) ) ENGINE=InnoDB; delete from t1 where id = 10;

可以看到,对索引 PRIMARY 加锁,mode = 1027,1027是什么意思呢?1027 = LOCK_REC_NOT_GAP + LOCK_X(非 gap 的记录锁且是 X 锁)

过程如下

结论:根据主键 id 去删除数据,且没有其它索引的情况下,此 SQL 只需要在 id = 10 这条记录上对主键索引加 X 锁即可

场景2:通过唯一索引进行删除

表结构做了微调,增加了 name 的唯一索引

构造数据 CREATE TABLE `t2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT "", PRIMARY KEY (`id`), UNIQUE KEY `uk_name` (`name`) ) ; INSERT INTO `t2` (`id`, `name`) VALUES (1,"M"), (2,"Y"), (3,"S"), (4,"Q"), (5,"L"); 测试sql语句 delete from t2 where name = "Y"

来看实际源码调试的结果 第一步:

第二步:
结论:这个过程是先对唯一键 uk_name 加 X 锁,然后再对聚簇索引(主键索引)加 X 锁

过程如下

场景3:通过普通索引进行删除

构造数据 CREATE TABLE `t3` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT "", PRIMARY KEY (`id`), KEY `idx_name` (`name`) ); INSERT INTO `t3` (`id`, `name`) VALUES (1,"N"), (2,"G"), (3,"I"), (4,"N"), (5,"X"); 测试语句: delete from t3 where name = "N";

调试过程如图:

结论:通过普通索引进行更新时,会对满足条件的所有普通索引加 X 锁,同时会对相关的主键索引加 X 锁

过程如下

场景4:不走索引进行删除

CREATE TABLE `t4` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT "", PRIMARY KEY (`id`) ) INSERT INTO `t4` (`id`, `name`) VALUES (1,"M"), (2,"Y"), (3,"S"), (4,"Q"), (5,"L"); delete from t4 where name = "S";

总共有 5 把 X 锁,剩下的 3 把就不一一放上来了

结论:不走索引进行更新时,sql 会走聚簇索引(主键索引)对全表进行扫描,因此每条记录,无论是否满足条件,都会被加上X锁。还没完... 但是为了效率考量,MySQL做了优化,对于不满足条件的记录,会在判断后放锁,最终持有的,是满足条件的记录上的锁,但是不满足条件的记录上的加锁/放锁动作不会省略。

过程如下

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/6692.html

相关文章

  • 你和阿里资深架构师之间,差的不仅仅是年龄(进阶必看)

    摘要:导读阅读本文需要有足够的时间,笔者会由浅到深带你一步一步了解一个资深架构师所要掌握的各类知识点,你也可以按照文章中所列的知识体系对比自身,对自己进行查漏补缺,觉得本文对你有帮助的话,可以点赞关注一下。目录一基础篇二进阶篇三高级篇四架构篇五扩 导读:阅读本文需要有足够的时间,笔者会由浅到深带你一步一步了解一个资深架构师所要掌握的各类知识点,你也可以按照文章中所列的知识体系对比自身,对自己...

    huaixiaoz 评论0 收藏0
  • 如何在 Mac 下用 Clion 调试 MySQL 源码

    摘要:前面写了几篇文章来通过调试源码来分析死锁问题,有读者问如何用调试源码,这篇文章简单介绍一下如何在下调试。下载是宇宙第二强的公司旗下的一款工具,我们做用的用的用的都是出自这家,很好很强大。如果有什么问题可以留言或者加微信沟通。前面写了几篇文章来通过调试 MySQL 源码来分析死锁问题,有读者问如何用 IDE 调试源码,这篇文章简单介绍一下如何在 Mac 下调试。 之所以使用调试的方式来分析死锁...

    琛h。 评论0 收藏0
  • MySQL 死锁套路:唯一索引 S 锁与 X 锁的爱恨情仇

    摘要:上一篇文章介绍了使用调试源码的方式来查看死锁的过程,这篇文章来讲讲一个常见的案例。毫不夸张的说,有一半以上的死锁问题由唯一索引贡献,后面介绍的很多死锁的问题都跟唯一索引有关。上一篇文章介绍了使用调试 MySQL 源码的方式来查看死锁的过程,这篇文章来讲讲一个常见的案例。 毫不夸张的说,有一半以上的死锁问题由唯一索引贡献,后面介绍的很多死锁的问题都跟唯一索引有关。这次我们讲一段唯一索引 S ...

    Darkgel 评论0 收藏0
  • MySQL 死锁套路:一次诡异的批量插入死锁问题分析

    摘要:线上最近出现了批量的死锁,百思不得姐。死锁记录如下第一反应是批量,的顺序不一样导致的死锁。什么是隐式锁隐式锁的意思就是没有锁在插入记录时,是不加锁的。线上最近出现了批量insert的死锁,百思不得姐。死锁记录如下 2018-10-26T11:04:41.759589Z 8530809 [Note] InnoDB: *** (1) TRANSACTION: TRANSACTION 1202...

    afishhhhh 评论0 收藏0
  • MySQL - 事务的启动 / 设置 / 锁 / 解锁——入门

    摘要:行级锁,页级锁,表级锁。闻其名知其意,比较少见的是页级锁,它锁定的是一组相邻数据。排他锁允许获得排他锁的事务更新数据,阻止其他事务取得相同数据集的读写。意向排他锁事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的锁。 废话 本篇的名字简直可以起成《事务操作:从入门到放弃》。 力图解决:在MySQL 5.5 版本及更高版本时,使用事务的完整流程和细节记录,而无需面对...

    iOS122 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<