一文深度解析MySQL中的锁机制
来到golang学习网的大家,相信都是编程学习爱好者,希望在这里学习数据库相关编程知识。下面本篇文章就来带大家聊聊《一文深度解析MySQL中的锁机制》,介绍一下MySQL,希望对大家的知识积累有所帮助,助力实战开发!
技术是为了解决问题而生的,锁被用来实现隔离性,保证并发事务的正确性。下面将具体介绍一下锁机制。
两段锁 & 一次封锁
两段锁
数据库遵循的是两段锁协议,将事务分成两个阶段,加锁阶段和解锁阶段(所以叫两段锁)
加锁阶段:在加锁阶段只能进行加锁操作。
如果事务要读取对象,必须先获得共享锁。可以有多个事务同时获得一个对象的共享锁
如果事务要修改对象,必须先获得独占锁。只能有一个事务获得对象的独占锁。如果某个事务已经获得了对象的独占锁,则其他尝试获取锁(包括共享锁、独占锁)的事务必须等待,直到加锁成功才能继续执行
解锁阶段:在解锁阶段只能进行解锁操作。
事务要读取对象 ,必须先获得共享锁,这样防止幻读。事务要修改对象,必须先获得独占锁,这样防止脏写。
两段锁可以这样来实现:事务开始后就处于加锁阶段,一直到执行 rollback 或 commit 之前都是加锁阶段。rollback 和 commit 使事务进入解锁阶段,即在 rollback 或 commit 时释放持有的锁。
一次封锁
一次封锁法遵守两段锁协议。
一次封锁要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。
一次封锁存在的问题:
封锁时间被延长,并发度被降低:一次就将以后要用到的全部数据加锁,势必延长了封锁的时间,从而降低了系统的并发度。
不适合用在数据库:一次封锁不适合用在数据库中,因为在事务开始阶段,数据库并不知道会用到哪些数据。
一次封锁的好处:不会出现死锁。
为什么要使用两段锁呢?用完直接释放锁不行吗?
不行,用完直接释放会使事务的隔离性受到影响。具体介绍可以看下面的文章。Mysql 锁:灵魂七拷问 (youzan.com)
两段锁 的优劣局限
两段锁的优点 / 作用:
解决事务并发问题:防止脏写、脏读 ......
实现可串行化隔离:将两段锁与谓词锁结合使用,可以防止所有形式的写倾斜以及其他竞争条件,实现可串行化隔离
性能和实际串行相比:相比于实际串行来说,使用两段锁时,多个事务可以并发读取同一个对象
性能和一次封锁来比:相比于一次封锁,两段锁的锁定时间更短,事务并发性比一次封锁要好
两段锁的缺点:
性能:使用两段锁,事务吞吐量和查询响应时间相比于其他弱隔离级别下降非常多。部分原因在于锁的获取和释放本身的开销,但更重要的是其降低了事务的并发性。
访问延迟具有非常大的不确定性:假如一个事务需要等待另一个事务释放锁,另一个事务释放锁的时机是不确定的,因此等待它释放锁的耗时是不确定的。
死锁更加频繁:由于两段锁的加锁模式,死锁可能变得更为频繁。因而导致另一个性能问题,即如果事务由于死锁而被强行中止,应用层就必须从头重试,假如死锁过于频繁,则性能和效率必然大打折扣。
数据库系统会自动检测死锁情况,并强行中止其中的一个事务以打破僵局
由于使用了这么多的锁机制,所以很容易出现死锁现象 ,例如事务 A 可能在等待事务 B 释放它持有的锁, 而事务 B 在等待事务 A 释放它持有的锁。数据库系统会自动检测事务之间的死锁情况,并强行中止其中的一个事务以打破僵局,这样另一个可以继续向前执行 。而被中止的事务需要由应用层来重试。
MySQL 提供的锁
根据加锁的范围,MySQL 里面的锁大致可以分成全局锁、表级锁和行级锁三类。
全局锁
全局锁就是对整个数据库实例加锁。
给数据库实例加全局锁的命令:flush tables with read lock;(FTWRL)
释放锁的命令:unlock tables;(表级锁、行级锁释放也是这个命令)
加上全局锁之后,整个数据库处于只读状态,其他线程的以下语句会被阻塞:
数据更新语句(数据的增删改 insert、delete、update)
数据定义语句(DDL、包括建表、修改表结构等)
更新类事务的提交语句(更新类事务就是使用了类似 select * from t1 for update; 带 for update 的查询的事务)
全局锁的典型使用场景是,做全库逻辑备份。也就是把整库每个表存成 .sql 类型的文件。
全局锁的作用相当于是停止更新操作,拿到一个一致性视图。
MySQL 的在可重复读隔离级别下开启一个事务也可以拿到一个一致性视图,并且后者可以做到不影响更新操作。
官方自带了全量逻辑备份工具 mysqldump。
当 mysqldump 使用参数 –single-transaction 的时候,就会使用基于 MVCC 机制的一致性视图。
当 mysqldump 使用参数 –master-data 的时候,就会使用基于全局读锁的一致性视图。
表级锁
表级锁就是对表加锁。
MySQL 里面表级别的锁有三种:
表锁;
元数据锁(meta data lock,MDL);
意向锁。
表锁
表锁就是对整个数据表加锁。
给数据表加表锁的命令:lock table 表名 read /write;
释放表锁的命令和释放全局锁的命令一样,都是:unlock tables;。如果不手动释放表锁,在客户端断开的时候会自动释放表锁。
需要注意的是,lock tables 语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
举个例子,如果在线程 A 中执行 lock tables t1 read, t2 write; 这个语句,则其他线程写 t1、读写 t2 的语句都会被阻塞。同时,线程 A 在执行 unlock tables 之前,也只能执行读 t1、读写 t2 的操作。连写 t1 都不允许,自然也不能访问其他表。
意向锁
表锁分为:共享锁、独占锁。
如果我们想对整个数据表加共享锁,首先要确保表中没有记录被加独占锁
如果我们想对整个数据表加独占锁,首先要确保表中没有记录被加共享锁 / 独占锁
那么我们该如何来判断表中是否有记录被加独占锁 / 独占锁呢?我们可以通过遍历所有记录的方式来查看表中有没有被加锁的记录,而遍历的方式太慢了。
意向锁的提出就是为了加表级别的共享锁 和 独占锁时,快速判断表中的记录是否被上锁,以避免用遍历的方式来查看表中有没有被加锁的记录,提供判断速度。
意向锁分为:意向共享锁、意向独占锁:
当事务准备在某条记录上加 共享锁 时,需要先在表级别加一个 意向共享锁;
当事务准备在某条记录上加 独占锁 时,需要先在表级别加一个 意向独占锁。
这样,如果表级别存在 意向共享锁,就意味着表中有被加 共享锁 的记录;如果表级别存在 意向独占锁,就意味着表中有被加 独占锁 的记录。通过意向锁我们就可以快速判断表中是否有记录被加锁。
元数据锁
元数据锁(meta data lock,MDL)是 MySQL 5.5 版本引入的。
MDL 不需要显式使用,在访问一个表的时候会被自动加 MDL 锁。
MDL 锁分为:MDL 读锁、MDL 写锁:
DML 操作(数据的增删改查:insert、delete、update、select)加 MDL 读锁
DDL 操作(对表结构做变更操作)加 MDL 写锁。
MDL 锁的加锁、释放锁的规则:
MDL 读锁与 MDL 读锁互不干扰。
MDL 写锁与 MDL 写锁、MDL 写锁与 MDL 读锁相互阻塞。用来保证变更表结构操作的安全性。
MDL 锁使用两段锁:事务获得锁之后, 一直持有锁直到事务结束(包括提交或中止)。
MDL 锁作用是:防止 DDL 操作和 DML 操作并发,保证变更表结构操作的安全性。
需要注意的是,如果申请加 MDL 锁失败,那么再此之后的加锁申请都必须等待(公平锁机制,遵循先来先执行原则,先来的没有加锁成功,后来的不能加锁)。因此执行 DDL 操作时要格外注意,如果操作执行时间过长,后面的 DML 操作都将被阻塞较长时间。
行级锁
行级锁就是对记录加锁。
行级锁又分为各种类型,不同类型的行级锁的作用也不同,行级锁分为:
Record Lock:行锁,单个行记录的锁
Gap Lock:间隙锁,作用于记录与记录之间的空隙,作用仅仅是为了防止满足搜索条件的记录插入空隙(防止插入幻影记录)
Next-Key Lock:索引区间锁,本质是一个行锁 和 一个 Gap Lock 的结合体
只在可重复读或以上隔离级别下的特定操作才会加间隙锁。在 加读写锁的 select、update 和 delete 时,除了基于唯一索引(主键索引也属于唯一索引)的查询之外,基于其他索引查询时都会加间隙锁。
能够加 Gap Lock 的要求:
必须是可重复读或以上隔离级别
如果是 select,则必须以给读到的记录加读写锁的方式
可重复读隔离级别下的 select ... for update、select ... lock in share mode
可串行化隔离级别下的 select ...(加共享锁)以及上面两种手动加共享锁,排他锁的方式
必须是能够走索引的查询,如果是全表扫描的查询那么没有办法加 Gap Lock。
加锁规则:包含了两个 “原则”、两个 “优化” 和一个 “bug”。
原则 1:加锁的基本单位是 next-key lock。next-key lock 是前开后闭区间。
原则 2:查找过程中访问到的对象才会加锁。
优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
一个 bug:唯一索引上的范围查询会访问到不满足条件的第一个值为止。
共享锁 & 独占锁
表锁、元数据锁、行锁又都分为共享锁和独占锁。
共享锁 - 共享锁兼容:如果事务要读取对象 ,必须先以共享模式获得锁。可以有多个事务同时获得一个对象的共享锁
共享锁 - 独占锁、独占锁 - 独占锁互斥:如果事务要修改对象,必须先以独占模式获取锁。只能有一个事务获得对象的独占锁。如果某个事务已经获得了对象的独占锁,则其他尝试获取锁(包括共享锁、独占锁)的事务必须等待
今天带大家了解了MySQL的相关知识,希望对你有所帮助;关于数据库的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

- 上一篇
- 阿里云PolarDB-X获得了“2022 OSCAR尖峰开源项目和开源社区”

- 下一篇
- 石原子科技正式加入科技制造开源社区!
-
- 漂亮的彩虹
- 细节满满,码起来,感谢作者大大的这篇博文,我会继续支持!
- 2023-04-02 23:37:52
-
- 紧张的母鸡
- 受益颇多,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢作者分享博文!
- 2023-03-18 03:31:55
-
- 小巧的黑米
- 这篇技术贴真是及时雨啊,很详细,很好,已加入收藏夹了,关注up主了!希望up主能多写数据库相关的文章。
- 2023-03-11 21:16:41
-
- 数据库 · MySQL | 2天前 |
- MySQL设置中文界面,超简单教程来了!
- 332浏览 收藏
-
- 数据库 · MySQL | 2天前 | mysql 索引提示
- MySQL进阶必看!FORCE/USE/IGNOREINDEX用法大揭秘
- 182浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- 手把手教你写MySQL存储过程,小白也能轻松上手
- 163浏览 收藏
-
- 数据库 · MySQL | 2天前 | mysql group by
- MySQL分组查询优化:GROUPBY原理+索引优化超全解析
- 324浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- MySQL设置中文语言,轻松拥有中文界面
- 211浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- MySQL建库语句从入门到精通:创建数据库+设置字符集&排序规则(附实例)
- 176浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- 从零开始学MySQL数据库操作,小白轻松变大神!
- 496浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- MySQL插入日期到时间字段,轻松搞定日期格式
- 484浏览 收藏
-
- 数据库 · MySQL | 2天前 | mysql 数据压缩
- MySQL怎么实现高效压缩存储?表压缩+列式存储详细解读
- 272浏览 收藏
-
- 数据库 · MySQL | 2天前 | mysql JOIN优化
- MySQL优化JOIN操作:七大技巧教你提升关联查询速度
- 106浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- MySQL出现中文乱码?超详细解决方案一次性搞定
- 211浏览 收藏
-
- 数据库 · MySQL | 2天前 |
- MySQL主从复制这样配!搞懂这些参数,replication稳了~
- 131浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 508次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 21次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 50次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 58次使用
-
- 稿定PPT
- 告别PPT制作难题!稿定PPT提供海量模板、AI智能生成、在线协作,助您轻松制作专业演示文稿。职场办公、教育学习、企业服务全覆盖,降本增效,释放创意!
- 53次使用
-
- Suno苏诺中文版
- 探索Suno苏诺中文版,一款颠覆传统音乐创作的AI平台。无需专业技能,轻松创作个性化音乐。智能词曲生成、风格迁移、海量音效,释放您的音乐灵感!
- 60次使用
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览
-
- MySQL数据表简单查询
- 2023-01-10 101浏览