Mysql 锁学习笔记

Innodb锁

SQL 行锁类型说明
INSERT ...排他锁自动加锁
UPDATE ...排他锁自动加锁
DELETE ...排他锁 自动加锁
SELECT (正常)不加任何锁
SELECT ... LOCK IN SHARE MODE共享锁在 SELECT 之后加 LOCK IN SHARE MODE
SELECT ... FOR UPDATE排他锁在 SELECT 之后加 FOR UPDATE

共享锁与排它锁

以下是官网给出的定义,其实共享锁也称为读锁,排他锁可称写锁。

  • A shared (S) lock permits the transaction that holds the lock to read a row.

  • An exclusive (X) lock permits the transaction that holds the lock to update or delete a row.

翻译:

  • 共享锁是允许事务获取锁去读一行数据。
  • 排他锁是允许事务获取锁去更新或者删除一行数据。

锁兼容级别

共享锁S排它锁X
共享锁SYESNO
排它锁XNONO

注:以上YES代表可以共存,NO代表不能共存。

意向锁 - 表级锁

以下是官方给出的两种意向锁解释

  • An intention shared lock (IS) indicates that a transaction intends to set a shared lock on individual rows in a table.

  • An intention exclusive lock (IX) indicates that a transaction intends to set an exclusive lock on individual rows in a table.

翻译:

  • 意图共享锁(IS)表明事务打算对表中的单个行设置共享锁。
  • 意图排他锁(IX)表示事务打算对表中的单个行设置排他锁。

代码示例

SELECT…FOR SHARE设置IS锁,SELECT…FOR UPDATE设置一个IX锁。

The intention locking protocol is as follows:

  • Before a transaction can acquire a shared lock on a row in a table, it must first acquire an IS lock or stronger on the table.

  • Before a transaction can acquire an exclusive lock on a row in a table, it must first acquire an IX lock on the table.

意图锁定协议如下:

  • 在事务获得表中某一行的共享锁之前,它必须首先获得表上的IS锁或更强的锁。
  • 在事务获得表中某一行的排他锁之前,它必须首先获得该表上的IX锁。

表级锁类型兼容性

XIXSIS
XConflictConflictConflictConflict
IXConflictCompatibleConflictCompatible
SConflictConflictCompatibleCompatible
ISConflictCompatibleCompatibleCompatible

行锁

记录锁总是锁定索引记录,即使表没有定义索引。对于这种情况,InnoDB创建一个隐藏的聚集索引,并使用该索引进行记录锁定。

隐藏的聚集索引:MySQL :: MySQL 8.3 Reference Manual :: 17.6.2.1 Clustered and Secondary Indexes

  • 当你在一个表上定义一个PRIMARY KEY时,InnoDB使用它作为聚集索引。应该为每个表定义一个主键。如果没有逻辑上唯一且非空的列或列集可以使用主键,则添加一个自动增量列。自动递增列值是唯一的,并在插入新行时自动添加。
  • 如果你没有为一个表定义PRIMARY KEY, InnoDB使用第一个UNIQUE索引,并且所有的KEY列都定义为not NULL作为集群索引。
  • 如果一个表没有PRIMARY KEY或合适的UNIQUE索引,InnoDB会在包含行ID值的合成列上生成一个隐藏的集群索引GEN_CLUST_INDEX。这些行按照InnoDB分配的行ID排序。行ID是一个6字节的字段,随着新行插入而单调增加。因此,按行ID排序的行在物理上是按插入的顺序排列的。

代码示例

-- 事务A获取记录锁(共享锁)
START TRANSACTION;
SELECT * FROM table_name WHERE condition FOR SHARE;
-- 事务B尝试获取记录锁(排他锁)
START TRANSACTION;
SELECT * FROM table_name WHERE condition FOR UPDATE;

间隙锁

间隙锁是在索引记录之间的间隙上的锁,或者在第一个索引记录之前或最后一个索引记录之后的间隙上的锁。

如果id没有被索引,或者有一个非唯一的索引,语句将锁定前面的空白。间隙锁之间不冲突。

如果将事务隔离级别更改为READ COMMITTED,间隙锁失效。

代码示例

SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 For UPDATE;
//防止其他事务将值15插入到列t.c1中,无论列中是否已经存在这样的值,
因为范围中所有现有值之间的间隙被锁定。

临键锁 - 行锁加间隙锁

如果一个会话对索引中的记录R具有共享锁或排他锁,则另一个会话不能在索引顺序R之前的空白中插入新的索引记录。

左开右闭,即不锁住左边界,但会锁住右边界。临键锁的主要设计目的是为了解决所谓的“幻读”问题。
(-infinity, 1]
(1, 7]
(7, +infinity)

-- 使用临键锁查询数据

SELECT * FROM users WHERE id > 1 FOR UPDATE;

插入意向锁

插入意图锁是insert操作在行插入之前设置的一种间隙锁。这个锁以这样一种方式表示插入的意图,即插入到相同索引间隙中的多个事务如果不在间隙内的相同位置插入,则不需要彼此等待。

假设存在值为4和7的索引记录。分别尝试插入值为5和6的事务,在获得插入行上的排他锁之前,每个事务都用插入意图锁锁住4和7之间的间隙,但不会相互阻塞,因为行不冲突。

自增锁

AUTO-INC锁是一种特殊的表级锁,用于在具有AUTO_INCREMENT列的表中插入事务。在最简单的情况下,如果一个事务正在向表中插入值,那么任何其他事务都必须等待对该表进行自己的插入,以便第一个事务插入的行接收连续的主键值。

innodb_autoinc_lock_mode变量控制用于自动增量锁定的算法。它允许您选择如何在可预测的自动递增值序列和插入操作的最大并发性之间进行权衡。

SELECT的加锁规则 (RR)

查看锁状态命令

查看当前事务等待锁sql
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
使用sys.innodb_lock_waits系统视图(仅适用于MySQL 8.0及以上版本)
SELECT * FROM sys.innodb_lock_waits;
查看死锁信息(TRANSACTIONS)
SHOW ENGINE INNODB STATUS
查询所有进程
show processlist;
在使用的表
show open tables where in_use > 0;
查看当前出现的所有锁​​​​​​​
SELECT * FROM information_schema.INNODB_LOCKs;

3.0 前置条件

# 表结构(姓名、公司、工号)
userinfo (Id PK, username, company, usercode);# 表中包含四条记录
5, Gates, Microsoft, 24
7, Bezos, Amazon,35
11, Jobs, Apple,37
14, Elison, Oracle,38

3.1 主键检索

1. 记录存在的情况

# 5是存在的记录,行锁
mysql> select * from userinfo where id=5 for update;mysql> update userinfo set username = "Brand" where id = 5;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction# X 排他锁
# RECORD 记录锁
mysql> select * from performance_schema.data_lock_waits;
+---------------+-------------+
| lock_mode     | lock_type|
+---------------+-------------+
| X             | RECORD   |
+---------------+-------------+

2. 记录不存在的情况

# 6是不存在的记录,间隙锁,锁住的区间为(5,7),对应上面的前置条件
mysql> select * from userinfo where id = 6 for update;mysql>  insert into user values(6, 'Brand', 'Ali',100);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactio# X 排他锁 + Gap 间隙锁
# RECORD 记录锁
mysql> select * from performance_schema.data_lock_waits;
+---------------+-------------+
| lock_mode     | lock_type|
+---------------+-------------+
| X,GAP         | RECORD   |
+---------------+-------------+

3.2 唯一索引检索

与主键检索结果一致,因为这两种都是可以唯一确定索引值和区间范围的。

3.3 普通索引检索

1. 记录存在的情况 左开右闭

# 24是存在的记录,更新行锁,插入间隙锁。24要算在内,锁住的区间为 usercode的(-oo,35]
,对应上面的前置条件
mysql> select * from userinfo where usercode = 24 for update;mysql> insert into user values(6, 'Brand', 'Ali',25);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction# X 排他锁
# RECORD 记录锁  + Gap 间隙锁
mysql> select * from performance_schema.data_lock_waits;
+---------------+-------------+
| lock_mode     | lock_type|
+---------------+-------------+
| X,GAP         | RECORD   |
+---------------+-------------+

2. 记录不存在的情况 左开右闭

# 25是不存在的记录,间隙锁,锁住的区间为 usercode的(24,35],对应上面的前置条件
mysql> select * from userinfo where id = 25 for update;mysql>  insert into user values(6, 'Brand', 'Ali',26);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactio# X 排他锁 + Gap 间隙锁
# RECORD 记录锁
mysql> select * from performance_schema.data_lock_waits;
+---------------+-------------+
| lock_mode     | lock_type|
+---------------+-------------+
| X,GAP         | RECORD   |
+---------------+-------------+

3.4 索引的范围检索

索引包括主键(默认)、唯一索引和其他普通索引

mysql> select * from userinfo where id > 4 for update;mysql> insert into user values(66, 'Brand', 'Ali',25);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction# X 排他锁 + Gap 间隙锁
# RECORD 记录锁
mysql> select * from performance_schema.data_lock_waits;
+---------------+-------------+
| lock_mode     | lock_type|
+---------------+-------------+
| X,GAP         | RECORD   |
+---------------+-------------+

3.5 普通检索(无索引)

表锁,因为需要扫描整张表。扫描期间所有的操作都不能被获取或变更。

3.6 总结

  • 事务隔离级别为可重复读(Repeated Read, RR)
  • 以主键或唯一索引作为查询条件,有存在值(记录)时是行锁,不存在值时触发间隙锁。
  • 普通索引作为查询条件,恒定间隙锁。
  • 索引作为查询条件,并以范围取值时,产生间隙锁。
  • 无索引时的普通检索,产生表锁。

参考文章

MySQL :: MySQL 8.3 Reference Manual :: 17.7.1 InnoDB Locking

https://www.cnblogs.com/wzh2010/p/18030866

https://www.cnblogs.com/qdhxhz/p/15598873.html

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

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

相关文章

【LeetCode刷题记录】19. 删除链表的倒数第 N 个结点

19 删除链表的倒数第 N 个结点 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 示例 1: 输入:head [1,2,3,4,5], n 2 输出:[1,2,3,5] 示例 2: 输入:head [1], n 1 输出…

大模型的实践应用22-谷歌Gemma AI大模型的架构原理,以及Gemma模型的部署安装本地教程

大家好,我是微学AI,今天给大家介绍一下大模型的实践应用22-谷歌Gemma AI大模型的架构原理,以及Gemma模型的部署安装本地教程。谷歌Gemma AI大模型是由Google AI团队开发并开源。Gemma模型采用Transformer编码器-解码器架构,并加入了一些改进,例如使用稀疏注意力机制来提高推…

Qt 运行 Android 程序时找不到 Toou2D 库闪退

问题描述 程序闪退,错误信息如下,找不到库。 W libAndroid10_armeabi-v7a.so: QQmlApplicationEngine failed to load component W libAndroid10_armeabi-v7a.so: qrc:/main.qml:3:1: plugin cannot be loaded for module "Toou2D": Cannot …

【vue2+antvx6】节点大小不一致,点击按钮流程图自动布局

需求: 1、点击优化布局的按钮,自动布局(从左到右),按钮变成撤销布局按钮 2、点击撤销布局的按钮,返回之前的布局 3、在点击优化布局的按钮后,如果移动了节点,则自动将撤销布局的按…

嵌入式Linux—Framebuffer应用编程

Framebuffer 应用编程 Frame的意思是帧,buffer的意思是缓冲区。Framebuffer就是一块内存(硬件设备),里面保存着一帧图像。 ioctl()函数解析 ioctl()函数非常强大。不同的驱动程序内部会实现不同的 ioctl() ,可以使用各种 ioctl() 跟驱动程序…

世媒讯提供海内外媒体宣发服务,引领企业新媒体发展之路

在这个信息化的时代,软文发稿已经成为企业发展不可或缺的重要工具。随着社会的快速发展,消费者需要更多定制化、个性化的信息。利用软性推广,凭借其细致入微的信息传递,可以迅速抓住消费者的注意力,从而进一步推动企业…

“五之链”第十六期沙龙活动在呆马科技成功举办

2024年4月19日,由临沂呆码区块链网络科技有限公司(呆马科技)承办的第十六期“五之链”物流主题沙龙活动成功举办。此次活动邀请了政府相关部门、知名科研院所、物流企业等20余家单位参与,共同探讨物流数据要素流通与智能应用的发展…

Redisson - 看门狗机制(Watch Dog)禁用方案

问题描述 Redis - Redisson tryLock 函数参数分析-CSDN博客 我们在这篇文章有提到过看门狗机制,其实有时候我们不想要看门狗机制的时候,如何禁用呢?!因为有时候不想续期,需要实时性比较高的业务,但是看门…

使用prompt_toolkit构建交互式命令行工具

prompt_toolkit是一个python库,用于构建命令行工具和终端应用。其官网介绍如下, prompt_toolkit is a library for building powerful interactive command line and terminal applications in Python. 安装命令如下, pip install prompt_to…

STM32 DAP

STM32 DAP DAP(Debug Access Port)是一种调试访问端口,通常与调试接口一起使用,例如JTAG或SWD。DAP的作用是提供对目标设备内部的调试、测试和编程访问权限,允许开发人员通过调试工具与目标设备进行通信,并…

朴素贝叶斯算法分类

def loadDataSet():postingList[[my, dog, has, flea, problems, help, please], #切分的词条[maybe, not, take, him, to, dog, park, stupid],[my, dalmation, is, so, cute, I, love, him],[stop, posting, stupid, worthless, garbage],[mr, licks, ate, my, steak, …

HarmonyOS开发案例:【相机开发】

基本概念 相机是OpenHarmony多媒体进程提供的服务之一,提供了相机的录像、预览、拍照功能,支持多用户并发取流。 在进行应用的开发前,开发者应了解以下基本概念: 视频帧 视频流指的是将一系列图片数据按照固定时间间隔排列形成的…

2024新算法爱情进化算法(LEA)和经典灰狼优化器(GWO)进行无人机三维路径规划设计实验

简介: 2024新算法爱情进化算法(LEA)和经典灰狼优化器(GWO)进行无人机三维路径规划设计实验。 无人机三维路径规划的重要意义在于确保飞行安全、优化飞行路线以节省时间和能源消耗,并使无人机能够适应复杂环…

Leetcode 第 393 场周赛题解

Leetcode 第 393 场周赛题解 Leetcode 第 393 场周赛题解题目1:3114. 替换字符可以得到的最晚时间思路代码复杂度分析 题目2:3115. 质数的最大距离思路代码复杂度分析 题目3:3116. 单面值组合的第 K 小金额思路代码复杂度分析 题目4&#xff…

ubuntu 18.04系统的镜像源

1 国内可用的镜像源 Ubuntu官方下载地址阿里云开源镜像站清华大学开源镜像站中国科技大学开源镜像站华为云开源镜像站 2 ubuntu 18.04 镜像说明 Ubuntu 18.04 是一个广泛使用的Linux发行版,它有多个版本的镜像可供下载。 在物理机上安装的镜像 如带desktop字样的…

使用BibTeX导入参考文献到Overleaf项目(常用方法)

使用bib为overleaf导入参考文献的好处 整洁的管理: 使用 .bib 文件可以使你的参考文献管理更加整洁和有条理。你可以将所有的参考文献集中存储在一个文件中,而不是在文档中直接引用或复制粘贴。 易于维护和更新: 当你需要添加、删除或修改参考…

申请泛域名证书步骤

泛域名证书的广泛应用范围: 泛域名证书不同于普通的单域名数字证书和多域名数字证书,可以一次以一张证书对应无限多的域名,在功能性和方便性上远优于一般证书。 单域名证书顾名思义,一张证书只对应一个独立域名,多域…

迅睿CMS内容删除后ID重置与指定起始值操作指南

在使用迅睿CMS进行内容管理时,经常会涉及到内容的增删改查。本文将介绍如何在删除内容后重置ID值,或指定ID值从某一特定数开始自增,以便于更好的管理数据。 ID重置操作 共享模块ID重置 在执行删除操作时,若需要对共享模块的内容…

Unity类银河恶魔城学习记录13-4 p145 Save Skill Tree源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili GameData.cs using System.Collections; using System.Collections.Generic…

投票刷礼物链接怎么弄?最新投票活动创建系统源码 轻松创建活动

投票刷礼物链接怎么弄?投票活动创建系统的作用和功能多种多样,为用户提供一个便捷、高效且功能强大的平台,用于创建、管理和执行各种投票活动。分享一个最新投票活动创建系统源码,源码开源可二开,含完整代码包和详细搭…