【MySQL】锁(黑马课程)
【MySQL】锁
- 0. 锁的考察点
- 1. 概述
- 1. 锁的分类
- 1.1 属性分类
- 1.2 粒度分类
- 2. 全局锁
- 2.1 全局锁操作
- 2.2.1 备份问题
- 3. 表级锁
- 3.1 表锁
- 3.2 语法
- 3.3 表共享读锁(读锁)
- 3.4 表独占写锁(写锁)
- 3.5 元数据锁(meta data lock, MDL)
- 3.6 意向锁
- 3.6.1 意向锁的种类
- 3.6.2 兼容关系
- 3.6.3 意向锁测试
- 4. 行级锁
- 附录
0. 锁的考察点

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

1.1 属性分类
InnoDB存储引擎实现了两种标准的行级锁:共享锁(S Lock)和排他锁(X Lock)。
共享锁(S Lock):允许事务读一行数据。
排他锁(X Lock):允许事务删除或更新一行数据。
1.2 粒度分类
按照锁的粒度来分,分为以下三类
- 全局锁:锁定数据库中的所有表。
- 表级锁:每次操作锁住整张表。
- 行级锁:每次操作,锁住对应的行数据。
2. 全局锁
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。
其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
如果不上锁,边备份,业务还正常执行就会造成数据不一致的问题。

2.1 全局锁操作
mysql> flush tables with read lock; // 加全局锁
Query OK, 0 rows affected (0.01 sec)mysql> insert into migrations values(7,'1231231',1); // 插入数据的时候
ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lockmysql> unlock tables; // 销毁全局锁
Query OK, 0 rows affected (0.00 sec)mysql> insert into migrations values(7,'1231231',1); // 可以正常插入了
Query OK, 1 row affected (0.01 sec)
备份数据库(newdb3)的数据
(base) ➜ ~ mysqldump -u root -p newdb3>/Users/fanzhen/Downloads/newdb3.sql
Enter password:
2.2.1 备份问题
全局锁特点
数据库中加全局锁,是一个比较重的操作,存在以下问题:
-
如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆。
-
如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。
在InnoDB引擎中,我们可以在备份时加上参数-single-transaction参数来完成不加锁的一致性数据备份。

3. 表级锁
表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中。
对于表级锁,主要分为以下三类:
- 表锁
- 元数据锁(meta data lock, MDL)
- 意向锁
3.1 表锁
对于表锁,分为两类:
- 表共享读锁(read lock) 简称读锁
- 表独占写锁(write lock) 简称写锁
3.2 语法
1. 加锁: lock tables 表名 read/write
2. 释放锁:unlock tables; 或者 客户端断开连接
3.3 表共享读锁(读锁)
如下图,当对一张表加读锁,我们可以看到,不同的客户端都可以进行查询操作,但是进行DDL与DML都会阻塞,当进行unlock tables操作时,其他进行DML、DDL操作的客户端获取资源,操作阻塞的SQL语句。



3.4 表独占写锁(写锁)
提示:排他锁,又称为写锁、独占锁
写锁在当前客户端既可以读也可以写,但是其他客户端既不能写也不能读。
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)mysql> lock tables migrations write;
Query OK, 0 rows affected (0.01 sec)mysql> select * from migrations;
+----+-------------------------------------------------------+-------+
| id | migration | batch |
+----+-------------------------------------------------------+-------+
| 1 | 2014_10_12_000000_create_users_table | 1 |
| 2 | 2014_10_12_100000_create_password_resets_table | 1 |
| 3 | 2019_08_19_000000_create_failed_jobs_table | 1 |
| 4 | 2019_12_14_000001_create_personal_access_tokens_table | 1 |
| 5 | 2024_03_31_143916_create_posts_table | 1 |
| 6 | 2024_04_01_143040_create_blogs_table | 1 |
| 7 | dagenihao | 1 |
+----+-------------------------------------------------------+-------+
7 rows in set (0.00 sec)


3.5 元数据锁(meta data lock, MDL)
MDL加锁过程是系统自动控制,无需显式使用,在访问一张表的时候会自动加上。MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免DML与DDL冲突,保证读写的正确性。
在MySQL5.5中引入了MDL,当对一张表进行增删改查的时候,加MDL读锁(共享);当对表结构进行变更操作的时候,加MDL写锁(排他)。

// 客户端1
mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from migrations;
+----+-------------------------------------------------------+-------+
| id | migration | batch |
+----+-------------------------------------------------------+-------+
| 1 | 2014_10_12_000000_create_users_table | 1 |
| 2 | 2014_10_12_100000_create_password_resets_table | 1 |
| 3 | 2019_08_19_000000_create_failed_jobs_table | 1 |
| 4 | 2019_12_14_000001_create_personal_access_tokens_table | 1 |
| 5 | 2024_03_31_143916_create_posts_table | 1 |
| 6 | 2024_04_01_143040_create_blogs_table | 1 |
| 7 | dagenihao | 1 |
+----+-------------------------------------------------------+-------+
7 rows in set (0.00 sec)
// 当客户端2执行完 update migrations set migration = 'MDL' where id = 7;
mysql> select * from migrations;
+----+-------------------------------------------------------+-------+
| id | migration | batch |
+----+-------------------------------------------------------+-------+
| 1 | 2014_10_12_000000_create_users_table | 1 |
| 2 | 2014_10_12_100000_create_password_resets_table | 1 |
| 3 | 2019_08_19_000000_create_failed_jobs_table | 1 |
| 4 | 2019_12_14_000001_create_personal_access_tokens_table | 1 |
| 5 | 2024_03_31_143916_create_posts_table | 1 |
| 6 | 2024_04_01_143040_create_blogs_table | 1 |
| 7 | dagenihao | 1 |
+----+-------------------------------------------------------+-------+
7 rows in set (0.00 sec)
mysql> commit-> ;
Query OK, 0 rows affected (0.00 sec)------------------------第二个例子-----------------------------------
mysql> bagin;
mysql> select * from migrations;
+----+-------------------------------------------------------+-------+
| id | migration | batch |
+----+-------------------------------------------------------+-------+
| 1 | 2014_10_12_000000_create_users_table | 1 |
| 2 | 2014_10_12_100000_create_password_resets_table | 1 |
| 3 | 2019_08_19_000000_create_failed_jobs_table | 1 |
| 4 | 2019_12_14_000001_create_personal_access_tokens_table | 1 |
| 5 | 2024_03_31_143916_create_posts_table | 1 |
| 6 | 2024_04_01_143040_create_blogs_table | 1 |
| 7 | MDL | 1 |
+----+-------------------------------------------------------+-------+
7 rows in set (0.00 sec)
// 客户端2
mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> select * from migrations;
+----+-------------------------------------------------------+-------+
| id | migration | batch |
+----+-------------------------------------------------------+-------+
| 1 | 2014_10_12_000000_create_users_table | 1 |
| 2 | 2014_10_12_100000_create_password_resets_table | 1 |
| 3 | 2019_08_19_000000_create_failed_jobs_table | 1 |
| 4 | 2019_12_14_000001_create_personal_access_tokens_table | 1 |
| 5 | 2024_03_31_143916_create_posts_table | 1 |
| 6 | 2024_04_01_143040_create_blogs_table | 1 |
| 7 | dagenihao | 1 |
+----+-------------------------------------------------------+-------+
7 rows in set (0.00 sec)
mysql> update migrations set migration = 'MDL' where id = 7;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0mysql> commit;
Query OK, 0 rows affected (0.00 sec)------------------------第二个例子-----------------------------------
mysql> alter table migrations add column java int; // 不能进行修改会一直阻塞
查看元数据锁
select object_type,object_schema,object_name,lock_type,lock_duration from performance_schema.metadata_locks;
+-------------------+--------------------+----------------+---------------------+---------------+
| object_type | object_schema | object_name | lock_type | lock_duration |
+-------------------+--------------------+----------------+---------------------+---------------+
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| COLUMN STATISTICS | performance_schema | metadata_locks | SHARED_READ | STATEMENT |
| TABLE | performance_schema | metadata_locks | SHARED_READ | TRANSACTION |
| SCHEMA | performance_schema | NULL | INTENTION_EXCLUSIVE | TRANSACTION |
+-------------------+--------------------+----------------+---------------------+---------------+
13 rows in set (0.01 sec)
3.6 意向锁
为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。
说明:左侧线程A在执行的时候,先开启事物,然后执行update并会在这一行加上行锁,然后对该表加上意向锁,线程B要对这个表加上表锁,线程B要通过意向锁来决定能不能加表锁。

3.6.1 意向锁的种类
1.意向共享锁(IS):由语句select...lock in share mode添加
2.意向排他锁(IX):由insert、update、delete、select.. for update 添加
3.6.2 兼容关系
- 意向共享锁(IS):与表锁共享锁(read)兼容,与表锁排它锁(write)互斥。
- 意向排他锁(IX):与表锁共享锁(read)及排它锁(write)都互斥。意向锁之间不会互斥。
可以通过以下SQL查看意向锁及行锁的加锁情况。
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
3.6.3 意向锁测试
// TODO
4. 行级锁
行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。
InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。
对于行级锁,主要分为以下三类:
- 行锁(Record Lock):锁定单个行记录的锁,防止其他事务对此行进行update和delete。在RC、RR隔离级别下都支持。
- 间隙锁(Gap Lock):锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持
- 临键锁(Next-Key Lock):行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下支持。
// TODO
附录
- 徐庶MySQL锁 https://blog.csdn.net/bjjx123456/article/details/136180761
- 黑马讲解MySQL锁部分
相关文章:
【MySQL】锁(黑马课程)
【MySQL】锁 0. 锁的考察点1. 概述1. 锁的分类1.1 属性分类1.2 粒度分类 2. 全局锁2.1 全局锁操作2.2.1 备份问题 3. 表级锁3.1 表锁3.2 语法3.3 表共享读锁(读锁)3.4 表独占写锁(写锁)3.5 元数据锁(meta data lock, MDL)3.6 意向…...
1.10编程基础之简单排序--02:奇数单增序列
OpenJudge - 02:奇数单增序列http://noi.openjudge.cn/ch0110/02/ 描述 给定一个长度为N(不大于500)的正整数序列,请将其中的所有奇数取出,并按升序输出。 输入 共2行: 第1行为 N; 第2行为 N 个正整数,其间用空格间隔。 输出 增序输出的奇数序列,数据之间以逗号间隔。数…...
【leetcode78-81贪心算法、技巧96-100】
贪心算法【78-81】 121.买卖股票的最佳时机 class Solution:def maxProfit(self, prices: List[int]) -> int:dp[[0,0] for _ in range(len(prices))] #dp[i][0]第i天持有股票,dp[i][1]第i天不持有股票dp[0][0] -prices[0]for i in range(1, len(prices)):dp[…...
IEC62056标准体系简介-4.IEC62056-53 COSEM应用层
为在通信介质中传输COSEM对象模型,IEC62056参照OSI参考模型,制定了简化的三层通信模型,包括应用层、数据链路层(或中间协议层)和物理层,如图6所示。COSEM应用层完成对COSEM对象的属性和方法的访问ÿ…...
嵌入式应用开发之代码整洁之道
前言:本系列教程旨在如何将自己的代码写的整洁,同时也希望小伙伴们懂如何把代码写脏,以备不时之需,同时本系列参考 正点原子 , C代码整洁之道,编写可读的代码艺术。 #好的代码的特点 好的代码应该都有着几…...
iwconfig iwpriv学习之路
iwconfig和iwpriv是两个常用的wifi调试工具,最近需要使用这两个工具完成某款wifi芯片的定频测试,俗话说好记性不如烂笔头,于是再此记录下iwconfig和iwpriv的使用方式。 -----再牛逼的梦想,也抵不住傻逼般的坚持! ----2…...
【Docker-compose】搭建php 环境
文章目录 Docker-compose容器编排1. 是什么2. 能干嘛3. 去哪下4. Compose 核心概念5. 实战 :linux 配置dns 服务器,搭建lemp环境(Nginx MySQL (MariaDB) PHP )要求6. 配置dns解析配置 lemp Docker-compose容器编排 1. 是什么 …...
【记录】LaTex|LaTex 代码片段 Listings 添加带圆圈数字标号的箭头(又名 LaTex Tikz 库画箭头的简要介绍)
文章目录 前言注意事项1 Tikz 的调用方法:newcommand2 标号圆圈数字的添加方式:\large{\textcircled{\small{1}}}\normalsize3 快速掌握 Tikz 箭头写法:插入点相对位移标号node3.1 第一张图:插入点相对位移3.2 第二张图࿱…...
《框架封装 · Redis 事件监听》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
小白学webgl合集-Three.js加载器
THREE.TextureLoader: 用途: 加载单个图像文件并将其作为纹理应用到材质上。示例: const loader new THREE.DataTextureLoader(); loader.load(path/to/data.bin, function (texture) {const material new THREE.MeshBasicMaterial({ map: texture });const geometry new TH…...
【算法】字符串的排列
难度:中等 给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。 换句话说,s1 的排列之一是 s2 的 子串 。 示例 1: 输入:…...
5-3.损失函数
文章最前: 我是Octopus,这个名字来源于我的中文名–章鱼;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github ;这博客是记录我学习的点点滴滴,如果您对 Python、Java、AI、算法有兴趣,可以关注我的…...
SCSA第四天
ASPF FTP --- 文件传输协议 Tftp --- 简单文件传输协议 FTP协议相较于Tftp协议 ---- 1,需要进行认证 2,拥有一套完整的命令集 用户认证 防火墙管理员认证 ---- 校验登录者身份合法性 用户认证 --- 上网行为管理中的一环 上网用户认证 --- 三层认证…...
品牌策划必读:9本改变游戏规则的营销经典
作为深耕品牌十余年的策划人,这些年自学啃下的书不计其数。 这里特意挑选了几本知名度不高但是却非常有用的“遗珠”优质品牌策划书籍分享出来。 如果你是一位初步了解品牌的人,这些书籍既包含了品牌理论基础,也有实用的实践指导。 这些书…...
泛型
背景 优点 类型绝对安全避免强制类型转换 泛型类 定义 使用 举例 泛型类 // 泛型类 T就是类型参数 public class Generic<T>{// key这个成员变量的类型为T,T的类型由外部指定private T t;public void set(T t){this.t t;}public T get(){return t;} }使用 // 创建一个泛…...
react动态渲染列表与函数式组件
1.如何使用jsx语法动态渲染列表呢,下边我用一个例子来切实总结一下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scal…...
小程序内容管理系统设计
设计一个小程序内容管理系统(CMS)时,需要考虑以下几个关键方面来确保其功能完善、用户友好且高效: 1. 需求分析 目标用户:明确你的目标用户群体,比如企业、媒体、个人博主等,这将决定系统的功…...
HDFS 块重构和RedundancyMonitor详解
文章目录 1. 前言2 故障块的重构(Reconstruct)2.1 故障块的状态定义和各个状态的统计信息2.2 故障文件块的查找收集2.5.2.1 misReplica的检测2.5.2.2 延迟队列(postponedMisreplicatedBlocks)的构造和实现postponedMisreplicatedBlocks中Block的添加postponedMisreplicatedBloc…...
Power BI DAX常用函数使用场景和代码示例
Power BI函数表达式对于没有接触过的朋友可能会有些迷茫,花一点时间了解一下原理在学习一些常用的DAX函数,就可以解决工作中绝大部分问题,函数使用都是共同的。 以下是一些最常用的DAX函数,如聚合,计数,日期…...
机器学习与深度学习:区别与联系(含工作站硬件推荐)
一、机器学习与深度学习区别 机器学习(ML:Machine Learning)与深度学习(DL:Deep Learning)是人工智能(AI)领域内两个重要但不同的技术。它们在定义、数据依赖性以及硬件依赖性等方面…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...
统计学(第8版)——统计抽样学习笔记(考试用)
一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征(均值、比率、总量)控制抽样误差与非抽样误差 解决的核心问题 在成本约束下,用少量样本准确推断总体特征量化估计结果的可靠性(置…...
解决MybatisPlus使用Druid1.2.11连接池查询PG数据库报Merge sql error的一种办法
目录 前言 一、问题重现 1、环境说明 2、重现步骤 3、错误信息 二、关于LATERAL 1、Lateral作用场景 2、在四至场景中使用 三、问题解决之道 1、源码追踪 2、关闭sql合并 3、改写处理SQL 四、总结 前言 在博客:【写在创作纪念日】基于SpringBoot和PostG…...
