锁,在现实生活中是为我们想要隐藏于外界所使用的一种工具。在计算机中,是协调多个进程或县城并发访问某一资源的一种机制。在数据库当中,除了传统的计算资源(cpu、ram、i/o等等)的争用之外,数据也是一种供许多用户共享访问的资源。如何保证数据并发访问的一致性、有效性,是所有数据库必须解决的一个问题,锁的冲突也是影响数据库并发访问性能的一个重要因素。从这一角度来说,锁对于数据库而言就显得尤为重要。
1、MySQL中的锁
MySQL中有着Lock和Latch的概念,在数据库中,这两者都可以被称为“锁”,但是两者有着截然不同的含义。

Latch一般称为闩锁(轻量级的锁),因为其要求锁定的时间必须非常短。若持续的时间长,则应用的性能会非常差,在InnoDB引擎中,Latch又可以分为mutex(互斥量)和rwlock(读写锁)。其目的是用来保证并发线程操作临界资源的正确性,并且通常没有死锁检测的机制。
Lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放(不同事务隔离级别释放的时间可能不同)。
关于Latch更详细的讲解可以参考:关于MySQL latch争用深入分析与判断,本文主要关注的是Lock锁。
锁的类型
对数据的操作其实只有两种,也就是读和写,而数据库在实现锁时,也会对这两种操作使用不同的锁;InnoDB 实现了标准的行级锁,也就是共享锁(Shared Lock)和互斥锁(Exclusive Lock)。
共享锁(读锁),允许事务读一行数据。
排他锁(写锁),允许事务删除或更新一行数据。
而它们的名字也暗示着各自的另外一个特性,共享锁之间是兼容的,而互斥锁与其他任意锁都不兼容:

稍微对它们的使用进行思考就能想明白它们为什么要这么设计,因为共享锁代表了读操作、互斥锁代表了写操作,所以我们可以在数据库中并行读,但是只能串行写,只有这样才能保证不会发生线程竞争,实现线程安全。
锁的粒度
Lock锁根据粒度主要分为表锁、页锁和行锁。不同的存储引擎拥有的锁粒度都不同。

表锁
表级别的锁定是MySQL各存储引擎中最大颗粒度的锁定机制。该锁定机制最大的特点是实现逻辑非常简单,带来的系统负面影响最小。所以获取锁和释放锁的速度很快。由于表级锁一次会将整个表锁定,所以可以很好的避免困扰我们的死锁问题。
当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并发度大打折扣。
使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。
表锁的语法很简单:
# 获取表锁
LOCK TABLES
tbl_name [[AS] alias] lock_type
[, tbl_name [[AS] alias] lock_type] ...
lock_type:
READ [LOCAL]
| [LOW_PRIORITY] WRITE
# 释放表锁
UNLOCK TABLESMyISAM在执行查询前,会自动执行表的加锁、解锁操作,一般情况下不需要用户手动加、解锁,但是有的时候也需要显示加锁。比如:检索某一个时刻t1,t2表中数据数量。
LOCK TABLE t1 read, t2 read; select count(t1.id1) as 'sum' from t1; select count(t2.id1) as 'sum' from t2; UNLOCK TABLES;
页锁
页级锁定是MySQL中比较独特的一种锁定级别,在其他数据库管理软件中也并不是太常见。页级锁定的特点是锁定颗粒度介于行级锁定与表级锁之间,所以获取锁定所需要的资源开销,以及所能提供的并发处理能力也同样是介于上面二者之间。另外,页级锁定和行级锁定一样,会发生死锁。
在数据库实现资源锁定的过程中,随着锁定资源颗粒度的减小,锁定相同数据量的数据所需要消耗的内存数量是越来越多的,实现算法也会越来越复杂。不过,随着锁定资源颗粒度的减小,应用程序的访问请求遇到锁等待的可能性也会随之降低,系统整体并发度也随之提升。
使用页级锁定的主要是BerkeleyDB存储引擎。
行锁
行级锁定最大的特点就是锁定对象的粒度很小,也是目前各大数据库管理软件所实现的锁定颗粒度最小的。由于锁定颗粒度很小,所以发生锁定资源争用的概率也最小,能够给予应用程序尽可能大的并发处理能力而提高一些需要高并发应用系统的整体性能。
虽然能够在并发处理能力上面有较大的优势,但是行级锁定也因此带来了不少弊端。由于锁定资源的颗粒度很小,所以每次获取锁和释放锁需要做的事情也更多,带来的消耗自然也就更大了。此外,行级锁定也最容易发生死锁。
使用行级锁定的主要是InnoDB存储引擎。
总结
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
从锁的角度来说,表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web应用;而行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如一些在线事务处理(OLTP)系统。
2、InnoDB中的锁
意向锁
上节提到InnoDB 支持多种粒度的锁,也就是行锁和表锁。为了支持多粒度锁定,InnoDB 存储引擎引入了意向锁(Intention Lock)。
那什么是意向锁呢?我们在这里可以举一个例子:如果没有意向锁,当已经有人使用行锁对表中的某一行进行修改时,如果另外一个请求要对全表进行修改,那么就需要对所有的行是否被锁定进行扫描,在这种情况下,效率是非常低的;不过,在引入意向锁之后,当有人使用行锁对表中的某一行进行修改之前,会先为表添加意向互斥锁(IX),再为行记录添加互斥锁(X),在这时如果有人尝试对全表进行修改就不需要判断表中的每一行数据是否被加锁了,只需要通过等待意向互斥锁被释放就可以了。
与上一节中提到的两种锁的种类相似的是,意向锁也分为两种:
意向共享锁(IS):事务想要在获得表中某些记录的共享锁,需要在表上先加意向共享锁。
意向互斥锁(IX):事务想要在获得表中某些记录的互斥锁,需要在表上先加意向互斥锁。
随着意向锁的加入,锁类型之间的兼容矩阵也变得愈加复杂:

jquery实现的滑动解锁
jquery实现的滑动解锁
539
查看详情
意向锁其实不会阻塞全表扫描之外的任何请求,它们的主要目的是为了表示是否有人请求锁定表中的某一行数据。
行锁的算法
InnoDB存储引擎有3种行锁的算法,其分别是:
Record Lock:单个行记录上的锁。
Gap Lock:间隙锁,锁定一个范围,但不包含记录本身。
Next-Key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身。
Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时InnoDB存储引擎会使用隐式的主键来进行锁定。
Next-Key Lock是结合了Gap Lock和Record Lock的一种锁定算法,在Next-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法。例如有一个索引有10,11,13和20这4个值,那么该索引可能被Next-Key Locking的区间为:

除了Next-Key Locking,还有Previous-Key Locking技术。同样上述的值,使用Previous-Key Locking技术,那么可锁定的区间为:

但是不是所有索引都会加上Next-key Lock的,在查询的列是唯一索引(包含主键索引)的情况下,Next-key Lock会降级为Record Lock。
接下来,我们来通过一个例子解释一下。
CREATE TABLE z (
a INT,
b INT,
PRIMARY KEY(a), // a是主键索引
KEY(b) // b是普通索引
);
INSERT INTO z select 1, 1;
INSERT INTO z select 3, 1;
INSERT INTO z select 5, 3;
INSERT INTO z select 7, 6;
INSERT INTO z select 10, 8;这时候在会话A中执行 SELECT * FROM z WHERE b = 3 FOR UPDATE ,索引锁定如下:

这时候会话B执行的语句落在锁定范围内的都会进行waiting
SELECT * FROM z WHERE a = 5 LOCK IN SHARE MODE; INSERT INTO z SELECT 4, 2; INSERT INTO z SELECT 6, 5;
用户可以通过以下两种方式来显示的关闭Gap Lock:
将事务的隔离级别设为 READ COMMITED。
将参数innodb_locks_unsafe_for_binlog设置为1。
从上面的例子可以看出来,Gap Lock的作用是为了阻止多个事务将记录插入到同一个范围内,设计它的目的是用来解决Phontom Problem(幻读问题)。在MySQL默认的隔离级别(Repeatable Read)下,InnoDB就是使用它来解决幻读问题。
幻读是指在同一事务下,连续执行两次同样的SQL语句可能导致不同的结果,第二次的SQL可能会返回之前不存在的行,也就是第一次执行和第二次执行期间有其他事务往里插入了新的行。
一致性非锁定读
一致性非锁定读(consistent nonlocking read)是指InnoDB存储引擎通过多版本控制(MVCC)的方式来读取当前执行时间数据库中行的数据。如果读取的这行正在执行DELETE或UPDATE操作,这时读取操作不会向XS锁一样去等待锁释放,而是会去读一个快照数据。MVCC相关的知识我已经在另外一篇文章中阐述了,这里就不做过多原理的分析了。地址:谈谈MySQL InnoDB存储引擎事务的ACID特性

在事务隔离级别RC和RR下,InnoDB存储引擎使用非锁定的一致性读。然而对于快照数据的定义却不同,在RC级别下,对于快照数据,非一致性读总是读取被锁定行的最新一份快照数据。而在RR级别下,对于快照数据,非一致性读总是读取事务开始时的行数据版本。
下面我们通过一个例子来看看大家是否对MVCC理解了。

可以看到,第1步和第2步是非常容易理解的,而在第3步事务B插入一条新的数据后,在第4步事务A还是查不到,也就是利用了MVCC的特性来实现。当事务B提交后,第5步的查询在RC和RR隔离级别下的输出是不同的,这个的原因在另一篇博客中也说到了,是因为他们创建ReadView的时机不同。
但是很诡异的是在第6步的时候,事务A更新了一条它看不见的记录,然后查询就能够查询出来了。这里很多人容易迷惑,不可见不代表记录不存在,它只是利用了可见性判断忽略了而已。更新成功之后,事务A顺其自然的记录了这条记录的Undo log,在随后的查询中,因为它能够看见自己的改动这一个可见性的判断,自然就能够查询出来了。这里很多名词需要去深入读一下此文:谈谈MySQL InnoDB存储引擎事务的ACID特性
一致性锁定读
前面说到,在默认隔离级别RR下,InnoDB存储引擎的SELECT操作使用一致性非锁定读。但是在某些情况下,用户需要显式地对数据库读取操作进行加锁以保证数据逻辑的一致性。InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作。
SELECT … FOR UPDATE (X锁)
SELECT … LOCK IN SHARE MODE (S锁)
3、锁带来的问题
通过锁定机制可以实现事务隔离性要求,使得事务可以并发的工作。锁提高了并发,但是却会带来潜在的问题。不过好在有事务隔离性的要求,不同的隔离级别解决的锁的问题也不同,这里只进行简单的介绍,不进行举例分析了。

InnoDB存储引擎在RR级别就已经解决了所有问题,但是它和Serializable的区别在哪里呢?区别就在于RR级别还存在一个丢失更新问题,而SERIALIZABLE无论对于查询还是更新都会进行锁定操作。

如图所示,用户原始金额为100,如果程序中对于转账和存款的判断是先查询再更新的话就会出现丢失更新的问题,也就是后面的更新覆盖了前面的更新。如果想避免这种问题,只能每次更新的时候金额基于表里最新的值来做。如果必须要先查询再更新,可以在更新的条件里判断金额(乐观锁),也可以使用隔离级别最高的SERIALIZABLE。
4、死锁
死锁是指两个或两个以上的事务在执行过程中,因争夺锁资源而造成的一种互相等待的现象,这里直接放上之前项目中遇到的一个死锁问题以及深入的分析:由一次线上问题带来的MySQL死锁问题分析,这里就不再赘述了。
推荐教程:《Mysql教程》
以上就是MySQL的锁详解的详细内容,更多请关注其它相关文章!
# 这一
# 学网站推广难
# 莱芜网站营销与推广加盟
# 商务网站建设前景
# 电脑网站优化流程
# 美丽说seo分析
# 靖江网站建设管理模式
# 太原b2b平台整合营销推广方案
# 律师网站建设科技公司
# 抖音小说关键词搜索排名
# 张诗林seo
# mysql
# 是指
# 也会
# 镜像
# 加锁
# 两种
# 的是
# 互斥
# 解锁
# 死锁
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
优化推广96088 】
【
技术知识133117 】
【
IDC资讯59369 】
【
网络运营7196 】
【
IT资讯61894 】
相关推荐:
《理想汽车》权限管理设置方法
PDF文件去水印平台入口 PDF水印删除网址
晨报|开发商暗示《空洞骑士:丝之歌》DLC开发中 《合金装备4》有望重制
学习通网页版课程打不开_课程无法访问时的解决方法
智学网app怎么登录忘记密码_智学网app忘记密码找回与重新登录操作方法
快递查询,一键速查
win11自带录屏文件保存在哪里 Win11 Game Bar录制视频默认路径【分享】
创客贴登录页面入口 创客贴网页版最新网址链接
如何在CSS中使用absolute实现登录弹窗居中_transform translate结合
mysql如何限制远程访问_mysql远程访问限制方法
智慧职教mooc平台登录网址 智慧职教mooc官网直达
小米手机截图后如何查看历史_小米手机截图历史记录查看方法
泰拉瑞亚水晶无法放置问题
高德地图怎么查看未来行程规划_高德地图未来行程规划查看方法
苹果手机聊天记录删除了如何恢复
高德地图导航路线偏差报警频繁怎么办 高德地图路线偏差修复与优化方法
PHP页面重载后变量状态保持:实现用户档案连续浏览的教程
Firefox OS应用开发:解决XMLHttpRequest跨域请求阻塞问题
百度小说看书时如何翻页_百度小说手动翻页与自动翻页设置
Mac hosts文件在哪里_Mac修改hosts文件详细教程
支付宝网页版在线入口 支付宝官网电脑登录入口
Word如何将文字快速转成表格 Word文本转换成表格功能使用技巧【效率】
Pydantic 中“schema”字段命名冲突的解决方案
Python测试中模块导入路径解析的最佳实践
解决Windows上Composer PATH变量冲突导致的命令无法识别问题
iPhone 14 Pro如何更改区域设置_iPhone 14 Pro地区语言修改教程
Win10如何关闭开机锁屏界面_Windows10跳过锁屏直接登录设置
Python高效统计字典嵌套列表值在目标列表中的出现次数
微博网页版访问入口 微博网页版网页端使用指南
怎样让Windows 11的开始菜单恢复经典样式_Open-Shell工具使用指南【怀旧】
小米civi如何设置锁屏时间
Yandex浏览器官方入口_Yandex搜索引擎中文版
百度竞价WAP显示PC链接问题
《我的恋爱逃生攻略》中文名字输入方法
顺丰官方查单号入口 顺丰快递单号查询官网入口
Golang如何使用gRPC拦截器实现日志收集_Golang gRPC拦截器日志收集实践
极兔快递官网查询入口手机版 手机极兔快递登录查询入口官方
139邮箱登录入口官网 139邮箱登录入口官网网址
构建可配置的J*aScript加权点击计数器与共享总计功能
如何在vscode中关闭it环境
《sketchbook》选中部分图案移动方法
《火影忍者:木叶高手》快速升级攻略
《战地6》反作弊已成功拦截240万次作弊 发售第一周98%比赛没有作弊
tiktok国际版入口_tiktok官网网页版链接
J*a里如何处理ArithmeticException并防止除零_算术异常防护策略解析
在Django单元测试中优雅处理信号:基于环境的条件执行策略
学习通网页版个人登录_学习通网页版个人账户登录入口
《星露谷物语》克林特好感度事件介绍
Cassandra中复合主键、二级索引与ORDER BY排序的限制与解决方案
晓晓优选app支付宝绑定方法
2020-04-29
运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。