mysql锁-这条sql加了哪些锁

2024-02-27 06:52
文章标签 sql mysql database 这条

本文主要是介绍mysql锁-这条sql加了哪些锁,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 1、 InnoDB的三种行锁
  • 2、常见的加锁语句
    • 2.1、常见隐式加锁语句
    • 2.1、常见显示加锁语句
  • 3、加锁的2条规则
  • 4、案例
    • 4.1、唯一索引等值查询
    • 4.2、唯一索引范围查询
    • 4.3、非唯一索引等值查询
    • 4.4、非唯一索引范围查询

InnoDB 存储引擎中的行锁的加锁规则。

1、 InnoDB的三种行锁

Record Lock(记录锁):锁住某一行记录
Gap Lock(间隙锁):锁住一段左开右开的区间
Next-key Lock(临键锁):锁住一段左开右闭的区间 (next-key lock 实际就是 间隙锁+记录锁)

2、常见的加锁语句

2.1、常见隐式加锁语句

1)、党见的DML语句(update、delete、insert),InnoDB 会自动给相应的记录行加写锁
2)、默认情况下对于普通 SELECT 语句,InnoDB 不会加任何锁,但是在 Serializable 隔离级别下会加行级读锁

2.1、常见显示加锁语句

1)、SELECT * FROM table_name WHERE … FOR UPDATE,加行级写锁

2)、SELECT * FROM table_name WHERE … LOCK IN SHARE MODE,加行级读锁

3、加锁的2条规则

1)查找过程中访问到的对象才会加锁

2)加锁的基本单位是 Next-key Lock

4、案例

一张order表,id为主键(唯一索引),order_id普通索引(非唯一索引),remark普通列(无索引)

idorder_idremark
104a
158b
2016c
2532d
3064e

4.1、唯一索引等值查询

唯一索引等值查询时,查询的记录是否存在,加锁的规则也会不同:
1)查询记录存在时,Next-key Lock会退化成记录锁
2)查询记录不存在时,Next-key Lock会退化成间隙锁

  • 查询记录存在
 SELECT * from t_order to2 where id = 25 for update;

结合加锁的两条核心:查找过程中访问到的对象才会加锁 + 加锁的基本单位是 Next-key Lock(左开右闭),我们可以分析出,这条语句的加锁范围是 (20, 25]

不过,由于这个唯一索引等值查询的记录 id = 25 是存在的,因此,Next-key Lock 会退化成记录锁,因此最终的加锁范围是 id = 25 这一行

可以在mysql客户端开启2个事物验证:

事物一:
start transaction; 
//锁住记录Id= 25的这条
select * from t_order to2 
where id = 25
for update
commit;
事物二:
start transaction; 
//可以插入成功
insert into t_order(id,order_id,remark )values('21','44','f')
rollback;
  • 查询的记录不存在

再来看查询的记录不存在的案例:

SELECT * from t_order to2 where id = 21;

结合加锁的两条核心:查找过程中访问到的对象才会加锁 + 加锁的基本单位是 Next-key Lock(左开右闭),我们可以分析出,这条语句的加锁范围是 (20, 25]

为什么是 (20,25] 而不是 (20, 22],因为 id = 22 的记录不存在,InnoDB 先找到 id = 20 的记录,发现不匹配,于是继续往下找,发现 id = 25,因此,id = 25 的这一行被扫描到了,所以整体的加锁范围是 (20, 25]

事物一:
start transaction; 
//锁住记录Id= 25的这条
select * from t_order to2 
where id = 25
for update
commit;
事物二:
start transaction; 
//阻塞,等待事物一提交,
insert into t_order(id,order_id,remark )values('21','44','f')
rollback;

4.2、唯一索引范围查询

唯一索引范围查询的规则和等值查询的规则一样,只有一个区别,就是唯一索引的范围查询需要一直向右遍历到第一个不满足条件的记录

select * from t_order to2 
where id >= 20 and id < 22
for update;

先来看语句查询条件的前半部分 id >= 20,因此,这条语句最开始要找的第一行是 id = 20,结合加锁的两个核心,需要加上 Next-key Lock (15,20]。又由于 id 是唯一索引,且 id = 20 的这行记录是存在的,因此会退化成记录锁,也就是只会对 id = 20 这一行加锁。

再来看语句查询条件的后半部分 id < 22,由于是范围查找,就会继续往后找第一个不满足条件的记录,也就是会找到 id = 25 这一行停下来,然后加 Next-key Lock (20, 25],重点来了,但由于 id = 25 不满足 id < 22,因此会退化成间隙锁,加锁范围变为 (20, 25)
所以,上述语句在主键 id 上的最终的加锁范围是 Record Lock id = 20 以及 Gap Lock (20, 25)

4.3、非唯一索引等值查询

非唯一索引进行等值查询的时候,根据查询的记录是否存在,加锁的规则会有所不同:
1、当查询的记录是存在的,除了会加 Next-key Lock 外,还会额外加间隙锁(规则是向下遍历到第一个不符合条件的值才能停止),也就是会加两把锁

查找记录的左区间加 Next-key Lock,右区间加 Gap lock

2、当查询的记录是不存在的,Next-key Lock 会退化成间隙锁(这个规则和唯一索引的等值查询是一样的)

  • 查询记录存在
select * from t_order to2 
where order_id =16
for update;

结合加锁的两条核心,这条语句首先会对普通索引 a 加上 Next-key Lock,范围是 (8,16]

又因为是非唯一索引等值查询,且查询的记录 order_id = 16 是存在的,所以还会加上间隙锁,规则是向下遍历到第一个不符合条件的值才能停止,因此间隙锁的范围是 (16,32)

所以,上述语句在普通索引order_id 上的最终加锁范围是 Next-key Lock (8,16] 以及 Gap Lock (16,32)。

验证,开启2个事物:

事物一:
start transaction; 
select * from t_order to2 
where order_id =16
for update;
commit;事物二:
start transaction; 
//阻塞,等待事物一提交
INSERT into t_order(id,order_id ,remark )values ('35','9','ffff')
commit;
  • 查询记录不存在
select * from t_order to2 
where order_id =18
for update;

结合加锁的两条核心,这条语句首先会对普通索引 order_id 加上 Next-key Lock,范围是 (16,32]

但是由于查询的记录order_id = 18 是不存在的,因此 Next-key Lock 会退化为间隙锁,即最终在普通索引 a 上的加锁范围是 (16,32)。

4.4、非唯一索引范围查询

范围查询需要一直向右遍历到第一个不满足条件的记录,和唯一索引范围查询不同的是,非唯一索引的范围查询并不会退化成 Record Lock 或者 Gap Lock。

start transaction; 
select * from t_order to2 
where order_id >=16 and order_id <18
for update;

先来看语句查询条件的前半部分 order_id >= 16,因此,这条语句最开始要找的第一行是 order_id = 16,结合加锁的两个核心,需要加上 Next-key Lock (8,16]。虽然非唯一索引 order_id = 16 的这行记录是存在的,但此时并不会像唯一索引那样退化成记录锁。

再来看语句查询条件的后半部分 order_id < 18,由于是范围查找,就会继续往后找第一个不满足条件的记录,也就是会找到 id = 32 这一行停下来,然后加 Next-key Lock (16, 32]。虽然 id = 32 不满足 id < 18,但此时并不会向唯一索引那样退化成间隙锁。

所以,上述语句在普通索引 a 上的最终的加锁范围是 Next-key Lock (8, 16] 和 (16, 32],也就是 (8, 32]。

这篇关于mysql锁-这条sql加了哪些锁的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/751543

相关文章

MySQL中比较运算符的具体使用

《MySQL中比较运算符的具体使用》本文介绍了SQL中常用的符号类型和非符号类型运算符,符号类型运算符包括等于(=)、安全等于(=)、不等于(/!=)、大小比较(,=,,=)等,感兴趣的可以了解一下... 目录符号类型运算符1. 等于运算符=2. 安全等于运算符<=>3. 不等于运算符<>或!=4. 小于运

虚拟机Centos7安装MySQL数据库实践

《虚拟机Centos7安装MySQL数据库实践》用户分享在虚拟机安装MySQL的全过程及常见问题解决方案,包括处理GPG密钥、修改密码策略、配置远程访问权限及防火墙设置,最终通过关闭防火墙和停止Net... 目录安装mysql数据库下载wget命令下载MySQL安装包安装MySQL安装MySQL服务安装完成

MySQL进行数据库审计的详细步骤和示例代码

《MySQL进行数据库审计的详细步骤和示例代码》数据库审计通过触发器、内置功能及第三方工具记录和监控数据库活动,确保安全、完整与合规,Java代码实现自动化日志记录,整合分析系统提升监控效率,本文给大... 目录一、数据库审计的基本概念二、使用触发器进行数据库审计1. 创建审计表2. 创建触发器三、Java

MySQL逻辑删除与唯一索引冲突解决方案

《MySQL逻辑删除与唯一索引冲突解决方案》本文探讨MySQL逻辑删除与唯一索引冲突问题,提出四种解决方案:复合索引+时间戳、修改唯一字段、历史表、业务层校验,推荐方案1和方案3,适用于不同场景,感兴... 目录问题背景问题复现解决方案解决方案1.复合唯一索引 + 时间戳删除字段解决方案2:删除后修改唯一字

Zabbix在MySQL性能监控方面的运用及最佳实践记录

《Zabbix在MySQL性能监控方面的运用及最佳实践记录》Zabbix通过自定义脚本和内置模板监控MySQL核心指标(连接、查询、资源、复制),支持自动发现多实例及告警通知,结合可视化仪表盘,可有效... 目录一、核心监控指标及配置1. 关键监控指标示例2. 配置方法二、自动发现与多实例管理1. 实践步骤

MySQL 主从复制部署及验证(示例详解)

《MySQL主从复制部署及验证(示例详解)》本文介绍MySQL主从复制部署步骤及学校管理数据库创建脚本,包含表结构设计、示例数据插入和查询语句,用于验证主从同步功能,感兴趣的朋友一起看看吧... 目录mysql 主从复制部署指南部署步骤1.环境准备2. 主服务器配置3. 创建复制用户4. 获取主服务器状态5

SpringBoot中六种批量更新Mysql的方式效率对比分析

《SpringBoot中六种批量更新Mysql的方式效率对比分析》文章比较了MySQL大数据量批量更新的多种方法,指出REPLACEINTO和ONDUPLICATEKEY效率最高但存在数据风险,MyB... 目录效率比较测试结构数据库初始化测试数据批量修改方案第一种 for第二种 case when第三种

MySql基本查询之表的增删查改+聚合函数案例详解

《MySql基本查询之表的增删查改+聚合函数案例详解》本文详解SQL的CURD操作INSERT用于数据插入(单行/多行及冲突处理),SELECT实现数据检索(列选择、条件过滤、排序分页),UPDATE... 目录一、Create1.1 单行数据 + 全列插入1.2 多行数据 + 指定列插入1.3 插入否则更

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

MySQL 迁移至 Doris 最佳实践方案(最新整理)

《MySQL迁移至Doris最佳实践方案(最新整理)》本文将深入剖析三种经过实践验证的MySQL迁移至Doris的最佳方案,涵盖全量迁移、增量同步、混合迁移以及基于CDC(ChangeData... 目录一、China编程JDBC Catalog 联邦查询方案(适合跨库实时查询)1. 方案概述2. 环境要求3.