首页 > 数据库 >MySQL 加锁案例--基于《MySQL 45 讲》的第 21 讲的总结

MySQL 加锁案例--基于《MySQL 45 讲》的第 21 讲的总结

时间:2024-07-02 12:59:44浏览次数:20  
标签:10 加锁 15 21 8.0 索引 MySQL id

前言

丁奇大佬的《MySQL 45 讲》可以说是每个 DBA boy 的必读经典,但教材中,大佬用的毕竟是 5.7 版本,日常用 8.0 的我还是得持怀疑的态度阅读文章。毕竟实践是检验真理的唯一标准。因此对 21 讲做了个总结(幸好 8.0 和 5.7 有出入,不然白搞了)。

案例总结+验证+一点点个人思考

秉承着能白嫖就不花钱的原则,贴上《45 讲》的链接,本文是对 21 讲的一个总结和验证:

21 为什么我只改一行的语句,锁这么多? | MySql实战45讲 (gitbook.io)

但花钱是能看评论区的,评论区的干货不比正文少(yes,我在叠甲)。

有关加锁规则的两个“原则”、两个“优化”和一个“bug”:

  • 原则1:加锁的基本单位是 next-key lock。next-key lock 是前开后闭区间。
  • 原则2:查找过程中访问到的对象才会加锁。
  • 优化1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
  • 优化2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
  • 一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。(8.0.34 无法复现,官方应该已经修复

示例数据:

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `c` int(11) DEFAULT NULL,
  `d` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `c` (`c`)
) ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);

下面我会在自己的 MySQL 8.0.34 版本上一一验证文章中的案例。有同学要问了,问得好!说你要怎么验证呢?很简单,开两个会话一一执行,观察结果就可以了。  

案例一:主键索引等值查询(8.0.34 版本验证一致)

  • update t set d = d + 1 where id = 7;
  • 原则1 + 优化2,加锁范围是主键上的 (5,10)

案例二:非唯一索引等值查询(8.0.34 版本验证一致)

  • select id from t where c = 5 lock in share mode;
  • 使用了覆盖索引,只给索引 c 加锁,主键不加锁
  • 原则1,加锁范围 (0,5];c 是普通索引,还要向右遍历,加锁范围 (5,10];优化2,加锁范围(5,10] 退化为 (5,10)
  • 总结:加锁范围索引 c 上的 (0,10)

案例三:主键索引范围查询(8.0.34 版本略有出入)

  • select * from t where id >= 10 and id < 11 for update;
  • 由于id是int,语义上跟 select * from t where id = 10 for update 是一样的,但加锁范围不一样
  • id=10 出发,从 (5,10] 退化为 id=10 上的行锁;继续向右找到 id=15,加 (10,15] 间隙锁
  • 但经过 8.0.34 版本的验证,id=15 上并没有锁,所以后面的版本应该做了优化,只加了 [10,15)
  • 总结:加锁范围是主键上的 [10,15)(《45 讲》原文是 [10,15])

案例四:非唯一索引范围查询(经 8.0.34 版本验证)

  • select * from t where c >= 10 and c < 11 for update;
  • 与案例三的分析过程一样,不同的是 c 是非唯一索引,所以没有用上优化 2,最终加锁范围是 (5,10] 和 (10,15] 两个 next-key lock
  • 总结:加锁范围是主键上的 (5,15]

案例五:唯一索引范围锁bug(8.0.34 版本已修复)

  • select * from t where id > 10 and id <= 15 for update;
  • 加锁范围 (10,15] 和 (15,20]
  • 8.0.34 只有 (10,15] 加了锁
  • 总结:加锁范围是主键上的 (10,15](《45 讲》原文是 (10,20])

案例六:非唯一索引上有相同值(8.0.34 版本验证一致)

  • 首先插入一行:insert into t values(30,10,30);使表中有两行c=10的记录
  • 然后:delete from t where c = 10;
  • 加锁范围如图(图中是索引c上的锁,主键上只锁住了id=10和id=30两行)

案例七:案例六+limit(8.0.34 版本验证一致)

  • delete from t where c = 10 limit 2;
  • 加了limit,找到了满足条件的数量后,就不需要再向右遍历了,所以加锁范围变成了
  • 有些网上流传的 MySQL 规范说 delete、update 不要加 limit,是考虑到了主从数据一致性,但这里可以看出,加 limit 能减小锁范围,也就是改善了并发度。因此 delete、update 加不加 limit 见仁见智。(是的,我的思考就这么一点点)

案例八:next-key 锁申请过程中,是先申请间隙锁,再申请行锁的(8.0.34 版本验证一致)

操作序列如下:

1. A的查询给索引c加上了 (5,10] 和间隙锁 (10,15);

2. B要 (5,10] 的间隙锁,进入锁等待(实际上已经获取了 (5,10),只是 [10] 不让获取,造成等待);

3. A 的插入被 B 的间隙锁锁住,出现死锁,B 的操作被回滚

结论:session B 的“加 next-key lock(5,10] ”操作,实际上分成了两步,先是加 (5,10) 的间隙锁,加锁成功;然后加 c=10 的行锁,这时候才被锁住的。如果是间隙锁和行锁一起作为整体获得,也就是第 2 步 B 什么锁也没拿到,那在第 3 步 A 的操作就不会造成死锁。

案例九:结尾问题(8.0.34 版本验证一致)

标签:10,加锁,15,21,8.0,索引,MySQL,id
From: https://blog.csdn.net/qq_37909315/article/details/140122026

相关文章

  • ubuntu安装mysql后修改密码
    一直没有接触ubuntu系统,今天在ubuntu上安装mysql,安装完成后发现修改密码不生效,拆腾好久。。。 切记使用root用户安装,要不然权限不够 sudoaptupdate#更新系统软件包列表sudoaptinstallmysql-server#安装MySQLServer#在安装过程中,系统可能要求设置root用户......
  • 基于Java+MySQL+SSM彩妆小样售卖商城
    系列文章目录项目介绍开发环境系统实现论文参考项目介绍随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于彩妆小样售卖商城当然也不能排除在外,随着网络技术的不断成熟,带动了彩妆小样售卖商城,它彻底改变了过去传统的管理方式,不......
  • 基于Java+MySQL+SSM斗车交易系统
    系列文章目录项目介绍系统环境系统实现论文参考项目介绍21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到准确、快速、完善,并能提高......
  • 基于Java+MySQL+SSM校园教务系统的设计与实现
    系列文章目录项目介绍开发环境系统实现论文参考项目介绍随着信息技术的迅猛发展,教育信息化已成为推动教育现代化、提高教育质量的重要手段。特别是在高等教育领域,学生数量持续增长,课程种类日益丰富,教务管理工作日趋复杂,传统的纸质记录和人工管理方式已难以满足日益增长......
  • 基于Java+MySQL+SSM舞蹈网站
    系列文章目录项目介绍开发环境系统实现论文参考项目介绍舞蹈作为一种艺术形式,不仅具有娱乐性,还有助于身心健康的发展。近年来,随着人们生活水平的提高和文化素养的增强,舞蹈文化逐渐普及并受到广大民众的喜爱。然而,传统的舞蹈教学方式和宣传渠道存在一定的局限性,难以满足......
  • 腾讯云服务器上安装mysql,本地windows机器通过heidisql客户端连接引发的问题
    一、问题描述1.腾讯云服务器上docker方式安装完mysql后,windows电脑上heidisql客户端不用密码就能连接2.修改docker里mysql密码,heidisql客户端就连接不上了二、问题排查1.不用密码就能连接是因为mysql的配置文件中有设置skip-grant-tables参数(1)dockerinspectsmysql查看挂......
  • 信息学奥赛初赛天天练-41-CSP-J2021基础题-n个数取最大、树的边数、递归、递推、深度
    PDF文档公众号回复关键字:202407012021CSP-J选择题单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)4.以比较作为基本运算,在N个数中找出最大数,最坏情况下所需要的最少比较次数为A.N^2B.NC.N-1D.N+16.对于有n个顶点、m条边的无向连通图(m>n),需要删......
  • 2.FineReport连接MySQL数据库
    1.服务器–定义数据连接2.添加JDBC3.配置连接4.添加数据库查询5.添加查询语句并预览结果......
  • MySQL之应用层优化(二)
    应用层优化Web服务器问题寻找最优并发度每个Web服务器都有一个最佳并发度——就是说,让进程处理请求尽可能快,并且不超过系统负载的最优的并发连接数。这就是前面说的最大系统容量。进行一个简单的测量和建模,或者只是反复试验,就可以找到这个"神奇的数",为此花一些时间是值得......
  • 基于web的酒店客房管理系统 毕业设计 springboot+Vue+mysql
    介绍我开发了一个基于Web的酒店客房管理系统,旨在通过现代化的管理工具提升酒店客房管理的效率和用户体验。该系统分为管理员角色和用户角色,管理员负责管理用户、客房信息、预约、入住、退房等内容,用户则可以查询客房信息、进行预约、管理入住和退房等操作。系统通过丰富的功能......