【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.mzph.cn/bicheng/50493.shtml

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

相关文章

室内消防逃生通道占用检测AI算法:科技筑防,守护生命通道

随着城市化进程的加快,高层建筑和大型公共场所的数量急剧增加,消防安全问题愈发凸显。其中,室内消防逃生通道的畅通性直接关系到火灾发生时人员的安全疏散。然而,由于各种原因,如杂物堆放、车辆停放等,消防…

LeetCode 2844.生成特殊数字的最少操作(哈希表 + 贪心)

给你一个下标从 0 开始的字符串 num ,表示一个非负整数。 在一次操作中,您可以选择 num 的任意一位数字并将其删除。请注意,如果你删除 num 中的所有数字,则 num 变为 0。 返回最少需要多少次操作可以使 num 变成特殊数字。 如…

前端知识--前端访问后端技术Ajax及框架Axios

一、异步数据请求技术----Ajax Ajax是前端访问后端的技术,为异步请求(不刷新页面,请求数据,只更新局部数据)。 例如:在京东网站中搜索电脑,就会出现一些联想搜索,但此时页面并没有…

Window下CLion实现本机通过socket通信-C++

1.引言-什么是socket socket即套接字,用于描述地址和端口,是一个通信链的句柄。应用程序通过socket向网络发出请求或者回应。 sockets(套接字)编程有三种,流式套接字(SOCK_STREAM),数据报套接字&#xff…

go语言开发Prometheus Exporter(DM数据库)

一、介绍 源码步骤基于dameng_exporter源码讲解,看完本篇文章可以直接进行二次开发。 dameng exporter的开源地址:https://github.com/gy297879328/dameng_exporter(可直接对接prometheusgrafana 提供表盘) 开发一个exporter 其…

Linux中的三类读写函数

文件IO和标准IO的区别 遵循标准: 文件IO遵循POSIX标准,主要在类UNIX环境下使用。标准IO遵循ANSI标准,具有更好的可移植性,可以在不同的操作系统上重新编译后运行。可移植性: 文件IO的可移植性相对较差,因为…

基于大模型零代码1小时完成国标数据分级分类近义词库构建及思考

1. 任务背景及困难分析 因项目要求,需要对国家标准国民经济行业分类-GB/T 4754-2017【1】进行近义词库的构建,时间非常紧,只给了很短时间进行处理,目标是构建一份中等粒度的行业近义词库。 搁在以前,可能需要点时…

Linux 安装mysql-client-core-8.0

在Linux上安装mysql-client-core-8.0 安装流程 下面是安装mysql-client-core-8.0的步骤和相应的命令: 步骤1:更新系统软件源 我们首先需要更新系统的软件源,以确保我们能够获取到最新的软件包列表。使用以下命令更新软件源: …

Ansible——inventory 主机清单

1、inventory 含义 Inventory支持对主机进行分组,每个组内可以定义多个主机,每个主机都可以定义在任何一个或多个主机组内。 如果是名称类似的主机,可以使用列表的方式标识各个主机。 vim /etc/ansible/hosts [webservers] 192.168.20.11:222…

平凯星辰亮相 2024 中国国际金融展,发布银行交易明细查询白皮书

7 月 19 日至 21 日,备受瞩目的 2024 中国国际金融展(以下简称金融展)在北京国家会议中心隆重举办。作为中国乃至亚洲最大的金融科技展会,本届金融展以“数字金融引领未来,守正创新共筑金融新生态”为主题,…

C++_单例模式

目录 1、饿汉方式实现单例 2、懒汉方式实现单例 3、单例模式的总结 结语 前言: 在C中有许多设计模式,单例模式就是其中的一种,该模式主要针对类而设计,确保在一个进程下该类只能实例化出一个对象,因此名为单例。而…

temu数据分析怎么做,temu选品数据分析怎么做

在竞争激烈的电商市场中,数据分析已成为商家提升销售业绩、优化经营策略的重要工具。特别是对于Temu平台的卖家而言,掌握数据分析技巧,特别是选品数据分析,更是至关重要。本文将为您详细解析如何在Temu平台上进行数据分析&#xf…

Docker 安全及日志管理(包含SSL证书)

目录 一、Docker 存在的安全问题 二、Docker 架构缺陷与安全机制 三、Docker 安全基线标准 四、容器相关的常用安全配置方法 五、限制流量流向 六、镜像安全 七、DockerClient 端与 DockerDaemon 的通信安全 https的单向认证流程 https的双向认证流程 八、DockerClie…

Ubuntu 22.04.4 LTS (linux) GoAccess 分析 Nginx 日志

1 安装goaccess sudo apt-get update sudo apt-get install goaccess 2 控制台运行 goaccess -a -d -f /usr/local/openresty/nginx/logs/access.log -p /etc/goaccess/goaccess.conf #sudo vim /etc/goaccess/goaccess.conf time-format %H:%M:%S date-format %d/%b…

iOS ------ Block的相关问题

Block的定义 Block可以截获局部变量的匿名函数&#xff0c; 是将函数及其执行上下文封装起来的对象。 Block的实现 通过Clang将以下的OC代码转化为C代码 // Clang xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m//main.m #import <Foundation/Foundation.…

3.2、数据结构-数组、矩阵和广义表

数组结构 数组是定长线性表在维度上的扩展,即线性表中的元素又是一个线性表。N维数组是一种“同构”的数据结构,其每个数据元素类型相同、结构一致。 一个m行n列的数组表示如下: 其可以表示为行向量形式&#xff08;一行一行的数据&#xff09;或者列向量形式&#xff08;一…

Nginx 怎样处理请求的故障转移?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01; 文章目录 Nginx 怎样处理请求的故障转移&#xff1f;一、理解故障转移的重要性二、Nginx 中的故障检测机制三、Nginx 中的请求分配策略四、Nginx 中的故障转移实现方式五、…

Shell脚本编程(一)

目录 一、Shell命令行的书写规则 二、编写/修改权限及执行shell程序的步骤 1、编写简单Shell程序 2、建立可执行程序 3、执行Shell程序 4、实例 三、Shell程序中使用参数 1、位置参数 2、内部参数 3、实例一 4、实例二 一、Shell命令行的书写规则 在执行Shell命令时…

搭建本地私有知识问答系统:MaxKB + Ollama + Llama3 (wsl网络代理配置、MaxKB-API访问配置)

目录 搭建本地私有知识问答系统:MaxKB、Ollama 和 Llama3 实现指南引言MaxKB+Ollama+Llama 3 Start buildingMaxKB 简介:1.1、docker部署 MaxKB(方法一)1.1.1、启用wls或是开启Hyper使用 WSL 2 的优势1.1.2、安装docker1.1.3、docker部署 MaxKB (Max Knowledge Base)MaxKB …

便携式气象仪:科技赋能,让气象观测更智能

随着科技的快速发展&#xff0c;越来越多的领域受益于技术的进步。其中&#xff0c;气象观测领域也不例外。传统的气象观测设备虽然精确可靠&#xff0c;但往往体积庞大、携带不便&#xff0c;且需要专业人员进行操作和维护。而便携式气象仪的出现&#xff0c;则打破了这一局限…