MySQL原理(三)锁定机制

news2025/1/12 6:10:03

一、介绍:

1、锁的本质

业务场景中存在共享资源,多个进程或线程需要竞争获取并处理共享资源,为了保证公平、可靠、结果正确等业务逻辑,要把并发执行的问题变为串行,串行时引入第三方锁当成谁有权限来操作共享资源的判断依据。因为数据库是多用户共享资源的,在并发环境下会破坏数据库的一致性,所以需要锁来控制它们。数据库锁机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则。

2、mysql术语
(1)DDL

data manipulation language, 它们是SELECT、UPDATE、INSERT、DELETE,就象它的名字一样,这4条命令是用来对 数据库里的数据 进行操作的语言;

(2)DML

data definition language, DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在 定义或改变表(TABLE)的结构 ,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用;

(3)DCL

Data Control Language,是数据库控制功能。是用来设置或更改数据库用户或角色权限 的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行DCL

3、按操作的颗粒分类

MySQL 数据库由于其自身架构的特点,存在多种数据存储引擎,每种存储引擎的锁定机制都是为各自所面对的特定场景而优化设计,所以各存储引擎的锁定机制也有较大区别。

存储引擎表级锁行级锁页面锁
MyISAM××
InnoDB×
MEMORY××
BDB×

除了以上几种粒度,还有一种全局锁(提到比较少)。后面分别介绍下。

4、按操作的类型分类

锁类型按照 操作类型划分 有「读锁(S锁),写锁(X锁)」,其实它们与共享锁,排他锁是一个意思,只是不同叫法而已。​​​​​​​

4.1、共享锁(读锁/S锁)

共享锁(Shared Lock)又称为读锁,简称S锁,是一种行级锁。

共享锁 就是多个事务对于同一数据共享一把锁,都能访问到数据,但是只能读不能修改。

# 加锁方式
select ... from ... lock in share mode;

# 事务提交或回滚释放:
commit;
rollback;
4.2、排他锁(写锁/X锁) 

排他锁(EXclusive Lock)又称为写锁,简称X锁,是一种行锁也可以是表锁。

排他锁 就是不能与其他锁并存,即当前写操作没有完成前,会阻断其他写锁和读锁。

注意:其他事务不加锁的读是不会被阻塞的,阻塞的是加锁的读

# 加锁方式:
# innodb引擎默认会在update,delete语句加上 for update
SELECT * FROM student FOR UPDATE; # 排他锁
INSERT INTO student values ...  # 排他锁
DELETE FROM student WHERE ...  # 排他锁
UPDATE student SET ...  # 排他锁

# 事务提交或回滚释放:
commit;
rollback;
4.3、意向锁(表锁) 

意向锁(Intention Lock) 简称 I锁,是表级锁的一种,它是由数据库引擎自行维护的,用户自己无需也无法操作意向锁。

意向锁 能够将 检查行锁 的时间复杂度由 O(n) 变成 O(1),其加锁的具体做法就是,当一个事务想要获取表中某一行的(共享/排他)锁的时候,它会自动尝试给当前表的加上意向(共享/排他)锁,用于防止全表扫描的一种锁。

(1)意向共享锁(IS锁-表级锁)
意向共享锁(Intention Shared Lock) 简称IS锁,事务想要给某一个数据行加行级共享锁(S锁)之前必须先获取该表的IS锁(表级锁)

(2)意向排他锁(IX锁-表级锁)
意向排他锁(Intention EXclusive Lock) 简称IX锁,事务想要给某一个数据行加行级排他锁(X锁)之前必须先获取该表的IX锁(表级锁)

4.4、意向锁的兼容互斥性

意向锁之间的兼容互斥性:意向锁之间是互相兼容的。

意向锁与其他锁兼容互斥性:意向锁与普通的排他锁/共享锁互斥(这的排他锁(X锁)共享锁(S锁)指的都是表锁,意向锁不会与行级的共享锁/排他锁互斥。上面表锁部分讲到的 显式加锁 加的就是排他锁/共享锁)。

5、按操作的性能分类

从操作的性能可分为乐观锁和悲观锁。乐观锁/悲观锁其实都是概念上的,只是在并发下防止数据被修改的一种加锁形式。

二、全局锁

1、介绍

全局锁就是对整个数据库实例加锁,主要被备份工具使用,使用 逻辑方式进行备份(mydumper,mysqldump) 或 物理方式进行备份(percona-xtrabackup) 。MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock ,简称 FTWRL ,保证了数据的一致性,在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。

2、加锁解锁
# 加锁
flush tables with read lock; # 即FTWRL,推荐使用 

# 解锁
unlock tables; 
3、弊端

加了全局锁之后,整个数据库都是【只读状态】,如果数据库里有很多数据,备份就会花费很多的时间,这样会造成业务停滞,有很大的弊端:

(1)备份期间,业务只能读数据,而不能更新数据;
(2)由于 FTWRL 需要关闭所有表对象,当这个时候还有长时间的 select 堵塞 FTWRL, 因为FTWRL会释放所有空闲的table缓存,如果有占用者占用某些table缓存,则会等待占用者自己释放这些table缓存,再去关闭表对象,执行命令时容易导致库卡死;
(3)如果在主库上备份。那么在备份期间都不能执行写入操作;
(4)如果在从库上备份。那么在备份期间,从库不能执行主库同步过来的 binlog,从而造成主从延时。

4、优化方法

如果数据库的引擎支持的事务支持 可重复读 的隔离级别,那么在备份数据库之前 先开启事务 ,会先创建 Read View,然后整个事务执行期间都在用这个 Read View,而且由于 MVCC 的支持,备份期间业务依然可以对数据进行更新操作。

官方自带的逻辑备份工具是 mysqldump。当 mysqldump 使用参数 –single-transaction 的时候,导数据之前就会启动一个事务,来确保拿到一致性视图。如果有的表使用了不支持事务的引擎,那么备份就只能通过 FTWRL 方法。这往往是 DBA 要求业务开发人员使用 InnoDB 替代 MyISAM 的原因之一。

三、表级锁

表锁 是 MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分 MySQL 引擎支持。当然,锁定颗粒度大所带来最大的负面影响就是出现锁定资源争用的概率也会最高,致使并大度大打折扣。

MySQL里面表级别的锁有两种:一种是 表锁,一种是 元数据锁(metadata lock,MDL) 。表锁一般是在数据库引擎不支持行锁的时候才会被用到的。默认使用表级锁定的主要是MyISAM,MEMORY,CSV等一些非事务性存储引擎。

1、表锁
# 隐式上锁(默认,自动加锁自动释放
insert、update、delete 上写锁
# 显式上锁(手动)
lock table tableName read; # 读锁/共享锁
lock table tableName write;# 写锁/排他锁

#解锁
unlock tables; # 客户端断开的时候也会自动释放锁。

# 查看表上加过的锁
show open tables;

 表级读锁会阻塞写操作,但是不会阻塞读操作。而写锁则会把读和写操作都阻塞。 

  • 表级读锁 : 当前表加read锁,当前连接和其他的连接都可以读操作;但是当前连接写操作会报错,其他连接写操作会被阻塞。

  • 表级写锁 : 当前表加write锁,当前连接可以对表做读写操作,其他连接对该表所有操作(读写操作)都被阻塞。

2、元数据锁
2.1、介绍:

metadata lock,简称 MDL。

Metadata lock 机制是为了保证数据一致性存在的。当有用户A查询一个表中的数据时,另一个用户B要对这个表结构做变更,删了一列,那么用户A拿到的结果跟表结构就不一致了,就会出现 waiting for table metadata lock。

Metadata lock 加锁过程是系统自动控制,无法直接干预,自动提交模式下,单语句就是一个事务,执行完了,事务也就结束了。

Metadata lock 是server层的锁,表级锁,每执行一条DML、DDL语句时都会申请 Metadata lock ,DML操作需要 Metadata lock 读锁,DDL操作需要 Metadata lock 写锁,读锁和写锁的阻塞关系如下:

  • 读锁和写锁之间相互阻塞,即同一个表上的DML和DDL之间互相阻塞。
  • 写锁和写锁之间互相阻塞,即两个会话不能对表同时做表定义变更,需要串行操作。

读锁和读锁之间不会产生阻塞。也就是增删改查不会因为 Metadata lock 产生阻塞,可以并发执行,日常工作中大家看到的Metadata lock 之间的锁等待是innodb行锁引起的,和 Metadata lock 无关。

申请 Metadata lock 的操作会形成一个队列,队列中写锁获取优先级高于读锁。一旦出现写锁等待,不但当前操作会被阻塞,同时还会阻塞后续该表的所有操作。事务一旦申请到 Metadata lock 后,直到事务执行完才会将锁释放。(这里有种特殊情况如果事务中包含DDL操作,mysql会在DDL操作语句执行前,隐式提交commit,以保证该DDL语句操作作为一个单独的事务存在,同时也保证元数据排他锁的释放)。

InnoDB行锁分类和 Metadata lock 很类似,也主要分为读锁和写锁,或者叫共享锁和排他锁,读写锁之间阻塞关系也一致。二者最重要的区别一个是表锁,一个是行锁,且行锁中的读写操作对应在 DML 中都属于读锁。

注意: 支持事务的InnoDB引擎表和不支持事务的MyISAM引擎表,都会出现Metadata Lock Wait等待现象。一旦出现Metadata Lock Wait等待现象,后续所有对该表的访问都会阻塞在该等待上,导致连接堆积,业务受影响。

2.2、解决方法

MDL 锁一旦发生会对业务造成极大影响,因为后续所有对该表的访问都会被阻塞,造成连接积压。要尽量避免 MDL 锁阻塞的发生:

(1)开启 metadata_locks 表记录 MDL 锁。

(2)设置参数 lock_wait_timeout 为较小值,使被阻塞端主动停止。

(3)规范使用事务,及时提交事务,避免使用大事务。

(4)增强监控告警,及时发现 MDL 锁。

(5)DDL 操作及备份操作放在业务低峰期执行。

四、行级锁

1、介绍

顾名思义,MySQL的行锁每次操作锁住一行数据,锁定粒度最小,发生锁冲突的概率最低,并发度最高,但开销大,加锁慢,而且会出现死锁。

2、原理

InnoDB行锁是通过对索引数据页上的记录加锁实现的,所以即使访问的不同记录,只要使用的是同一索引项,也可能会出现锁冲突。

3、实现算法

行锁主要实现算法有 3 种:Record LockGap Lock 和 Next-key Lock

(1)RecordLock锁(记录锁):锁定单个行记录的锁,如果表中没有主键和任何一个索引,那InnoDB会使用隐式的主键来进行锁定。(RC、RR隔离级别都支持)

(2)GapLock锁(间隙锁):锁定索引记录间隙,确保索引记录的间隙不变,但不包含记录本身。(RR隔离级别支持)

(3)Next-key Lock 锁(记录锁+间隙锁):记录锁和间隙锁组合,锁定数据前后范围,并且锁定记录本身。(RR隔离级别支持)

注意: 在RR隔离级别,InnoDB对于行的查询都是采用 Next-Key Lock 的组合锁定算法,但是 在查询的列是唯一索引(包含主键索引)的情况下Next-key Lock 会降级为 Record Lock ,仅锁住索引本身而非范围。

对于InnoDB,如果设置 AUTOCOMMIT = 1,如果没有 显式explicit(即写出begin transaction语句),任何一个语句,都是独立的一个事务,每个语句前面隐式(implicit)加了begin transaction,然后随后自动commit。如果设置AUTOCOMMIT = 0,没有写commit语句,那么所有的语句都在一个事务里,等着最后写一个commit去提交不管commit语句出现没有,都会有Redo Log和Undo Log(commit语句的标志会记录在Redo Log里)。

下面具体看下针对不同的sql语句采用的是那种加锁方式:

1)select ... from 语句:InnoDB引擎采用MVCC机制实现非阻塞读,所以对于普通的select语句,InnoDB不加锁。

2)select ... from lock in share mode语句:追加了共享锁,InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

3)select ... from for update语句:追加了排他锁,InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

4)update ... where 语句:InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

5)delete ... where 语句:InnoDB会使用Next-Key Lock锁进行处理,如果扫描发现唯一索引,可以降级为RecordLock锁。

6)insert语句:InnoDB会在将要插入的那一行设置一个排他的RecordLock锁。
4、两阶段加锁协议

两阶段加锁协议-S2PL(Strict-2PL):在一个事务里面,分为加锁(lock)阶段和解锁(unlock)阶段,也即所有的lock操作都在unlock操作之前,只有提交(commit)或者回滚(rollback)时才是解锁阶段,

事务A事务B
begin;
update user set k=k+1 where id = 1
update user set k=k+1 where id = 2
begin;
update user set k=k+1 where id = 1
commit

事务A持有的两个记录的行锁都是在commit的时候才释放的,事务B的update语句会被阻塞,直到事务A执行commit之后,事务B才能继续执行。

在InnoDB事务中,行锁是在需要的时候才加,但并不是不需要了就立刻释放,而是事务结束时释放。如果事务中需要锁多个行,要把最可能造成锁冲突,最可能影响并发度的语句尽量往后放。

5、死锁和死锁检测

并发系统中出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,会导致几个线程无限等待,称为死锁。

事务A在等待事务B释放id=2的行锁,而事务B在等待事务A释放id=1的行锁。事务A和事务B在互相等待对方的资源释放,就是进入了死锁状态。

6、死锁解决策略

(1)一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置。
(2)另一种策略是,发起 死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数innodb_deadlock_detect设置为on,表示开启这个逻辑。

五、页级锁

每次锁定相邻的一组记录,锁定粒度界于表锁和行锁之间,开销和加锁时间界于表锁和行锁之间,并发度一般,页级锁和行级锁一样,会发生死锁。应用在 BerkeleyDB存储引擎中,一般很少见,了解一下即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420499.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows Server 2025 LTSC 预览版来了

Windows Server 2025 LTSC 预览版来了 1. 安装 Windows Server 2025 LTSC 预览版2. 安装 VMware Tools3. Windows Server 2025 LTSC 预览版4. Windows Server 2025 LTSC 预览版下载地址 1. 安装 Windows Server 2025 LTSC 预览版 使用 VMware Workstation 安装, 安…

Mysql-事务(隔离级别,事务底层原理,MVCC)

什么是事务?有哪些特性? 事务:事务指的是逻辑上的一组操作,组成这组操作的各个单元要么全都成功,要么全都失败。 事务特性: 原子性(Atomicity): 原子性是指事务是一个不…

如何在 Ubuntu 中安装 Microsoft Edge 浏览器

微软终于聪明了一回,也学会了「打不过就加入」。Microsoft Edge 浏览器的 Linux 稳定版已经于 2020 年 10 月 23 日发布,并提供给 Linux 发行版使用。除了官方 Edge APT 源以外,还提供了.deb和.rpm格式的安装包。 Microsoft Edge 基于 Chrom…

###C语言程序设计-----C语言学习(7)#(调试篇)

前言:感谢您的关注哦,我会持续更新编程相关知识,愿您在这里有所收获。如果有任何问题,欢迎沟通交流!期待与您在学习编程的道路上共同进步。 一. 程序调试 1.程序调试介绍: 程序调试是软件开发过程中非常重…

大坑!react+thress.js

2. UI交互界面与Canvas画布叠加 | Three.js中文网 (webgl3d.cn) // canvas画布绝对定位 renderer.domElement.style.position absolute; renderer.domElement.style.top 0px; renderer.domElement.style.left 0px; renderer.domElement.style.zIndex -1; 我按照教程设置了…

C#小结:以Winform为例,总结一些C#在桌面开发中一些技巧

目录 一、给列表增加按钮&#xff0c;打印实体信息 二、嵌套子窗体 一、给列表增加按钮&#xff0c;打印实体信息 private void button1_Click(object sender, EventArgs e) {List<Student> studentList new List<Student>(){new Student() { Id 1, Name &quo…

Hadoop-MapReduce-源码跟读-MapTask阶段篇

一、源码下载 下面是hadoop官方源码下载地址&#xff0c;我下载的是hadoop-3.2.4&#xff0c;那就一起来看下吧 Index of /dist/hadoop/core 二、Mapper类 我们先看下我们写的map所继承的Mapper类 public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {/*** 传递…

python二维高斯热力图绘制简单的思路代码

import numpy as np import matplotlib.pyplot as plt from scipy.ndimage import gaussian_filter import cv2# 生成一个示例图像 image_size 100 image np.zeros((image_size, image_size))# 在图像中心创建一个高亮区域 center_x, center_y image_size // 2, image_size …

爱可声助听器参与南湖区价值百万公益助残捐赠活动成功举行

“声音大小合适吗&#xff1f;能听清楚吗&#xff1f;”今天下午&#xff0c;一场助残捐赠活动在南湖区凤桥镇悄然举行&#xff0c;杭州爱听科技有限公司带着验配团队和听力检测设备来到活动现场&#xff0c;为南湖区听障残疾人和老人适配助听器。 家住余新镇的75岁的周奶奶身体…

mac截图翻译软件有哪些?五大超实用翻译软件

mac截图翻译软件有哪些&#xff1f;随着全球化的发展&#xff0c;跨语言沟通已成为日常生活和工作中不可或缺的一部分。然而&#xff0c;语言障碍常常让我们在阅读外文资料时感到困惑。为了解决这一问题&#xff0c;Mac用户需要一款强大的截图翻译软件来帮助他们快速理解外文内…

Docker 搭建MySQL主从复制-读写分离

一. 介绍 MySQL主从复制是一种常用的数据库高可用性解决方案&#xff0c;通过在主数据库上记录的数据变更&#xff0c;同步到一个或多个从数据库&#xff0c;实现数据的冗余备份和读写分离。在Docker环境下搭建MySQL主从复制和读写分离&#xff0c;不仅方便管理&#xff0c;还…

MES和QMS怎么选?

MES&#xff0c;即制造执行系统&#xff0c;主要用于监控和控制生产过程&#xff0c;提升生产效率、减少生产成本。万界星空科技MES可以提供实时的生产数据&#xff0c;帮助企业做出更准确的决策&#xff0c;并且能够自动化地执行生产任务&#xff0c;提高生产线的效率和灵活性…

视频转GIF动图实践, 支持长视频转GIF

背景 找了很多GIF动图制作的工具&#xff0c;比如将视频转成GIF, 或者将一系列图片转成GIF, 增加背景文案等等功能。很多收费或者用的一些三方库有点点卡顿&#xff0c;或者需要安装一个软件&#xff0c;所以就自己做一款纯前端页面级别的 视频转 GIF 动图工具。 最开始找到一…

LLM漫谈(四)| ChatDOC:超越ChatPDF性能并支持更多功能的阅读聊天工具

在过去的一年里&#xff0c;ChatGPT的兴起催生了许多基于GPT的人工智能工具&#xff0c;其中Chat PDF工具得到了广泛关注。这些工具对知识密集型专业人员来说尤其有价值&#xff0c;大大提高了生产力。随着Chat PDF工具的激增&#xff0c;选择正确的工具变得至关重要。 接下来&…

vue-computed 计算属性

一、computed 计算属性 在Vue应用中&#xff0c;在模板中双向绑定一些数据或者表达式&#xff0c;但是表达式如果过长&#xff0c;或者逻辑更为复杂 时&#xff0c;就会变得臃肿甚至难以维护和阅读&#xff0c;例如&#xff1a; <div>写在双括号中的表达式太长了,不利于阅…

Apache Commons Collection3.2.1反序列化分析(CC1)

Commons Collections简介 Commons Collections是Apache软件基金会的一个开源项目&#xff0c;它提供了一组可复用的数据结构和算法的实现&#xff0c;旨在扩展和增强Java集合框架&#xff0c;以便更好地满足不同类型应用的需求。该项目包含了多种不同类型的集合类、迭代器、队…

LiveGBS流媒体平台GB/T28181功能-支持配置开启 HTTPS 服务什么时候需要开启HTTPS服务

LiveGBS功能支持配置开启 HTTPS 服务什么时候需要开启HTTPS服务 1、配置开启HTTPS1.1、准备https证书1.1.1、选择Nginx类型证书下载 1.2、配置 LiveCMS 开启 HTTPS1.2.1 web页面配置1.2.2 配置文件配置 2、验证HTTPS服务3、为什么要开启HTTPS3.1、安全性要求3.2、功能需求 4、搭…

2024 中国(南京)国际口腔设备器械博览会

2024 中国&#xff08;南京&#xff09;国际口腔设备器械博览会 时间&#xff1a;2024 年 7 月 18-20 日 地点&#xff1a;南京国际展览中心 WeChat_20230512134641 主办单位: 南京民营口腔医疗协会 北京铭曼国际展览有限公司 承办单位: 北京铭曼国际展览有限公司 展会介绍 随…

SpringCloudStream整合MQ

目录 概念 快速搭建SCS环境 一秒切换MQ 组件 1. Binder 2. Binding 3. Message 分组消费 概念 Spring Cloud Stream&#xff08;SCS&#xff09; 的主要目标是一套代码&#xff0c;兼容所有MQ, 降低MQ的学习成本&#xff0c;提供一致性的编程模型&#xff0c;让开发者能更…

Qt之窗口位置

Qt提供了很多关于获取窗体位置及显示区域大小的函数&#xff0c;如x&#xff08;&#xff09;&#xff0c;y()和pos()&#xff0c;rect()&#xff0c;size()&#xff0c;geometry()等&#xff0c;统称为"位置相关函数"或"位置函数"。几种主要位置函数及其之…