【MySQL进阶篇】锁:全局锁、表级锁以及行级锁

一、锁的概述

锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须要解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。因此,锁对数据库尤为重要,也更加复杂。

1.1、分类

1、全局锁:锁定数据库中的所有表。

2、表级锁:每次操作锁住整张表。

3、行级锁:每次操作锁住对应的行数据。

二、全局锁

全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。

其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,从而保证数据的完整性。

加上全局锁:

2.1、语法结构 

加锁:

FLUSH TABLES WITH READ LOCK;

执行数据备份:

MYSQLDUMP  -uroot -p指定密码 数据库名称>数据库名称.sql; 

 解锁:

UNLOCK TABLES;

flush tables with read lock ;
update score set chines=92 where id=1;
#解锁
unlock tables;
#数据备份,可以在cmd命令行中输入
mysqldump -hlocalhost -uroot -p0219423 staff_data > D:/staff_data.sql

 2.2、全局锁特点

数据库中加全局锁是一个比较重的操作,存在以下问题:

1、如果在主库上备份,那么在备份期间都不能执行更新,就业基本上陷入停摆;

2、如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志,会导致主从延迟。

在InnoDB引擎中我们可以在备份时加上参数 --single -transaction 参数来完成不加锁的一致性数据备份。

三、表级锁

表级锁,每次操作锁住整张表。锁的力度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、DBD等存储引擎中。

3.1、分类

对于表级锁,主要分为以下三类:

1、表锁

2、元数据所

3、意向锁

3.1.1、表锁

对于表锁,又可以分为两类:

1、表共享读锁(read lock):客户端一可以读取表数据,但不能进行写入,客户端二也是如此。

2、表独占写锁(write lock):客户端既能读取数据也可以写入数据,客户端二既不能读数据也不能写入数据。

#语法:

#1、加锁:

lock tables 表名...read/write;

#2、释放锁:

unlock tables/客户端断开连接;

3.1.2、元数据锁(MDL)

MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是为了维护表元数据的数据一致性,在表上有活动事务的时候,不可以队员数据进行写入操作。为了避免DDL与DML冲突,保证读写的正确性。 

在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构变更操作的时候,加上MDL写锁(排他)。

对应SQL锁类型说明
lock tables xxx read / write SHARED_READ_ONLY/SHARED_NO_READ_WRITE
select、select ... lock in share modeSHARED_READ与SHARED_READ、SHARED_WRITE兼容,与EXCLUSIVE互斥
insert、update、delete、select ... for updateSHARED_WRITE与SHARED_READ、SHARED_WRITE兼容,与EXCLUSIVE互斥
alter table ...EXCLUSIVE与其他的MDL都互斥
#客户端一执行select操作:begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from score;
+------+--------+--------+------+---------+
| id   | name   | chines | math | english |
+------+--------+--------+------+---------+
|    1 | 米老鼠 |     92 |   80 |      66 |
|    2 | 唐老鸭 |     67 |   88 |      91 |
|    3 | 杰瑞   |     76 |   71 |      77 |
|    4 | 汤姆   |     88 |   55 |      62 |
+------+--------+--------+------+---------+
4 rows in set (0.00 sec)
#客户端二执行修改表结构操作:begin;
Query OK, 0 rows affected (0.00 sec)mysql> alter table score add java int;
#到这里会发生阻塞,直到客户端1执行事务提交操作

 查看元数据锁:

select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;

3.1.3、意向锁 

为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。

过程:

线程A在执行的时候先开启事务,对某一行加上行锁,然后对整张表加上一个意向锁,线程B则对这张表加上表锁,在加表锁时,会去检查这张表中意向锁的情况,通过意向锁的情况来决定加锁是否能够成功,如果意向锁和我们当前所加的表锁是兼容的,就可以加锁;反之线程B则会处于阻塞状态,直至线程A提交事务,行锁与意向锁释放。

意向锁的分类:

1、意向共享锁(IS):由语句select ... lock in share mode添加;与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。

2、意向排他锁(IX):insert、update、delete、select ... for update添加;与表锁共享锁(read)及表锁排他锁(write)都互斥。意向锁之间不会互斥。

可以通过以下SQL来查看意向锁及行锁的加锁情况:

select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
#客户端一:begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from score where id=1 lock in share mode;
#客户端二:select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
+---------------+-------------+-----------------+-----------+-----------+------------------------+
| object_schema | object_name | index_name      | lock_type | lock_mode | lock_data              |
+---------------+-------------+-----------------+-----------+-----------+------------------------+
| staff_data    | score       | NULL            | TABLE     | IS        | NULL                   |
| staff_data    | score       | GEN_CLUST_INDEX | RECORD    | S         | supremum pseudo-record |
| staff_data    | score       | GEN_CLUST_INDEX | RECORD    | S         | 0x00000000022E         |
| staff_data    | score       | GEN_CLUST_INDEX | RECORD    | S         | 0x00000000022F         |
| staff_data    | score       | GEN_CLUST_INDEX | RECORD    | S         | 0x000000000230         |
| staff_data    | score       | GEN_CLUST_INDEX | RECORD    | S         | 0x000000000231         |
+---------------+-------------+-----------------+-----------+-----------+------------------------+
6 rows in set (0.00 sec)mysql> lock tables score write;
#此时由于IS是意向共享锁与写锁互斥,从而导致阻塞,直至客户端一事务提交

四、行级锁

行级锁,每次操作锁住对应的行数据,锁定力度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。

在InnoDB中数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。

4.1、行级锁的分类

 4.1.1、行锁(Record Lock)

锁定单个行记录的锁,防止其他事务对此行进行update和delete。在RC和RR隔离级别下都支持。

InnoDB引擎实现了以下两种类型的行锁:

1、共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。

2、排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。

当前锁类型\请求锁类型S(共享锁)X(排他锁)
S(共享锁)兼容冲突
X(排他锁)冲突冲突
SQL行锁类型说明
INSERT...排他锁自动加锁
UPDATE...排他锁自动加锁
DELETE...排他锁自动加锁
SELECT(正常)不加任何锁
SELECT ... LOCK IN SHARE MODE共享锁需要在SELECT之后手动加 LOCK IN SHARE MODE
SELECT ... FOR UPDATE排他锁需要在SELECT之后手动加 FOR UPDATE

默认情况下,InnoDB在REPEATABLE READ事务隔离级别运行,InnoDB使用next-key锁进行搜索和扫描索引,以防止幻读。

1、针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。 

 2、InnoDB的行锁是针对索引加的锁不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁。

#客户端一:begin;
Query OK, 0 rows affected (0.00 sec)select * from student where id=1;
+----+--------+------------+
| id | name   | no         |
+----+--------+------------+
|  1 | 黛丽丝 | 2000100101 |
+----+--------+------------+
1 row in set (0.00 sec)
#此时还未加上锁
mysql> select * from student where id=1 lock in share mode;
+----+--------+------------+
| id | name   | no         |
+----+--------+------------+
|  1 | 黛丽丝 | 2000100101 |
+----+--------+------------+
1 row in set (0.00 sec)
#客户端二:select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
Empty set (0.00 sec)mysql> select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
+---------------+-------------+------------+-----------+---------------+-----------+
| object_schema | object_name | index_name | lock_type | lock_mode     | lock_data |
+---------------+-------------+------------+-----------+---------------+-----------+
| test          | student     | NULL       | TABLE     | IS            | NULL      |
| test          | student     | PRIMARY    | RECORD    | S,REC_NOT_GAP | 1         |
+---------------+-------------+------------+-----------+---------------+-----------+
2 rows in set (0.00 sec)
mysql> update student set name='lily' where id=1;
#执行update语句会处于阻塞状态(共享锁与排他锁互斥)
#客户端一:begin;
Query OK, 0 rows affected (0.00 sec)mysql> update student set name='lily' where id=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
#客户端二:begin;
Query OK, 0 rows affected (0.00 sec)mysql> update student set name='lily' where id=1;
#排他锁与排他锁互斥,处于阻塞状态,直至客户端一的事务提交
#客户端一:begin;
Query OK, 0 rows affected (0.00 sec)mysql> update student set name='lili' where name='黛丽丝';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
#客户端二:update student set name='lei' where id=2;
#因为name字段无索引,会对所有记录加锁

4.1.2、间隙锁(Gap Lock)

锁定索引记录间隙(不含该记录),确保索引间隙记录不变,防止其他事务在这个间隙进行insert,产生幻读。在RR级别下支持。

默认情况下,InnoDB在REPEATABLE READ 事务隔离级别运行,InnoDB使用next-key进行搜索和扫描索引,以防止幻读。

1、索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁。

2、索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时Next-Key Lock退化为间隙锁。

3、索引上的范围查询(唯一索引)--会访问到不满足条件的第一个值为止。

#客户端一:select * from student;
+----+--------+------------+
| id | name   | no         |
+----+--------+------------+
|  1 | 黛丽丝 | 2000100101 |
|  2 | 谢逊   | 2000100102 |
|  3 | 殷天正 | 2000100103 |
|  4 | 韦一笑 | 2000100104 |
|  8 | lei    | 2000100108 |
+----+--------+------------+
5 rows in set (0.00 sec)mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> update student set name ='lili' where id=5;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0
#客户端二:select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
+---------------+-------------+------------+-----------+-----------+-----------+
| object_schema | object_name | index_name | lock_type | lock_mode | lock_data |
+---------------+-------------+------------+-----------+-----------+-----------+
| test          | student     | NULL       | TABLE     | IX        | NULL      |
| test          | student     | PRIMARY    | RECORD    | X,GAP     | 8         |
+---------------+-------------+------------+-----------+-----------+-----------+
2 rows in set (0.00 sec)begin;
Query OK, 0 rows affected (0.00 sec)mysql> insert into student values(7,'ruby',null);
#5和8之间存在间隙锁,插入数据会阻塞

注意:间隙锁唯一目的是防止其他事务插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一个间隙上采用间隙锁。 

4.1.3、临键锁(Next-Key Lock)

行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下都、支持。 

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

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

相关文章

基于Python的河南省天气数据分析与空气质量预测研究【含数据抓取与数据库自动存储】

有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主 抓取天气网站 以下是部分代码展示 import matplotlib.pyplot as plt# 设置中文字体 plt.rcParams[axes.unicode_minus] False # 不使用中文减号 plt.rcParams[font.sans-serif] FangSong # …

Python爬虫技术 第14节 HTML结构解析

HTML 结构解析是 Web 爬虫中的核心技能之一,它允许你从网页中提取所需的信息。Python 提供了几种流行的库来帮助进行 HTML 解析,其中最常用的是 BeautifulSoup 和 lxml。 1. 安装必要的库 首先,你需要安装 requests(用于发送 HTT…

Linux系统上安装zookeeper

百度网盘 通过网盘分享的文件:zookeeper_linux 链接: https://pan.baidu.com/s/1_hybXZVwTRkotz0VbwbSMw?pwd8888 提取码: 8888 1.将压缩包拖进虚拟机 2.解压压缩包 cd /ruanjian/zookeeper/ tar -zxvf apache-ZooKeeper-3.7.2-bin.tar.gz3. 进入到conf目录 cd …

Godot入门 03世界构建1.0版

在game场景,删除StaticBody2D节点,添加TileMap节点 添加TileSet图块集 添加TileSet源 拖动图片到图块,自动创建图块 使用橡皮擦擦除。取消橡皮擦后按住Shift创建大型图块。 进入选择模式,TileMap选择绘制,选中图块后在…

通过强大的语义层增强现代数据湖

在现代数据湖架构中,语义层通过向数据添加有意义的上下文来发挥至关重要的作用,否则这些上下文会丢失。此层充当现代数据湖(数据仓库和查询引擎)处理层中未整理的原始数据与利用此数据的工具和应用程序之间的桥梁。此服务对 AI 特…

【Golang 面试基础题】每日 5 题(七)

✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…

【中项】系统集成项目管理工程师-第5章 软件工程-5.6软件质量管理与5.7软件过程能力成熟度

前言:系统集成项目管理工程师专业,现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试,全称为“全国计算机与软件专业技术资格(水平)考试”&…

ROS机械臂——rviz+gazebo仿真环境搭建

纲要 ROS的控制插件 常用控制器 完善机器人模型 为link添加惯性参数和碰撞属性 为joint添加传动装置 添加gazebo控制插件 加载机器人模型 启动仿真环境 问题:gazebo加载的模型只有一层阴影 解决方案:关闭虚拟机,设置虚拟机属性,…

【数据结构-前缀和】力扣2550.统计范围内的元音字符串数

给你一个下标从 0 开始的字符串数组 words 以及一个二维整数数组 queries 。 每个查询 queries[i] [li, ri] 会要求我们统计在 words 中下标在 li 到 ri 范围内(包含 这两个值)并且以元音开头和结尾的字符串的数目。 返回一个整数数组,其中…

springboot实战(十二)之通过注解的方式记录接口出入参log入库

前言 生产过程中,为了更好的辅助线上问题排查避免不了对接口出入参进行日志输出的时候,并且为了分析接口数据效果需要将每次请求接口的出入参进行落库方便后续的数据分析,这时总不能每个接口入参之后、出参之前都打印一遍日志吧?如…

C++第十弹 ---- vector的介绍及使用

目录 前言vector的介绍及使用1. vector的使用1.1 vector的定义1.2 iterator的使用1.3 vector空间增长问题1.4 vector增删查改 2. vector迭代器失效问题(重点) 总结 前言 本文介绍了C中的vector数据结构及其使用方法。 更多好文, 持续关注 ~ 酷酷学!!! 正文开始 vector的介绍…

基本类型的包装类,面向对象三大特性,继承(inherit).一道力扣分享。

>>>基本类型的包装类 拆包–>封包 拆包–>包装类型转换为基本数据类型 封包—>基本数据类型转换为包装类型 编号基本数据类型包装类型1byteByte2shortShort3charCharacter4intInteger5longLong6floatFloat7doubleDouble8booleanBoolean 为何要用包装类型…

【echarts】中如何设置曲线展示最新值、最大值、最小值

需要用到的属性:图表标注 series-line. markPoint 默认可以通过 type直接标注:‘min’ 最小值、‘max’ 最大值、‘average’ 平均值。 markPoint: {data: [{type: max},{type: min}]}如何展示最新值 如果要展示最新值得话,需要设置 标注…

昇思25天学习打卡营第19天|DCGAN生成漫画头像

DCGAN生成漫画头像总结 实验概述 本实验旨在利用深度卷积生成对抗网络(DCGAN)生成动漫头像,通过设置网络、优化器以及损失函数,使用MindSpore进行实现。 实验目的 学习和掌握DCGAN的基本原理和应用。熟悉使用MindSpore进行图像…

Vue3时间选择器datetimerange在数据库存开始时间和结束时间

♥️作者:小宋1021 🤵‍♂️个人主页:小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!! 🎈🎈加油! 加油&#xff01…

[算法]归并排序(C语言实现)

一、归并排序的定义 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 二、归并排序的算法原理 归并排序的算法可以用递归法和非递归法来实现…

介绍一下TCP/IP 模型和 OSI 模型的区别

OSI 模型是由国际标准化组织制定的一个用于计算机或通信系统间互联的标准体系,一共有七层,由上而下分别为应用层,表示层,会话层,传输层,网络层,数据链路层和物理层,虽然 OSI 模型理论…

华为网络模拟器eNSP安装部署教程

eNSP是图形化网络仿真平台,该平台通过对真实网络设备的仿真模拟,帮助广大ICT从业者和客户快速熟悉华为数通系列产品,了解并掌握相关产品的操作和配置、提升对企业ICT网络的规划、建设、运维能力,从而帮助企业构建更高效&#xff0…

Geoscene Pro的数据管理

GeoScene Pro是为新一代WebGIS平台而全新打造的一款具有高效、强大生产力且为全面国产的的高级桌面应用程序,可以对来自本地、GeoScene Online、或者GeoScene Portal的数据进行可视化、编辑、分析,可以同时在2D和3D中制作内容,并发布为要素服…

医疗器械维修行业发展及趋势

医疗器械维修的前景是广阔的。‌ 随着医疗技术的不断发展和进步,‌医疗器械的种类和数量持续增加,‌对专业维修人员的需求也在不断上升。‌无论是医院、‌诊所等医疗机构,‌还是医疗器械生产企业、‌销售企业等,‌都需要专业的维修…