由delete语句引起的锁范围扩大
由delete语句引起的锁范围扩大
阿里云月报中的一句话,出处:http://mysql.taobao.org/monthly/2022/01/01/
但是Ghost Record是可以跟正常的Record一样作为Key Range Lock的加锁对象的。可以看出这相当于把删除操作变成了更新操作,因此删除事务不再需要持有Next Key Lock
这句话意思是:假设delete语句物理删除数据,那么delete事务会持有gap lock,那么会造成锁扩大,而实际上delete操作会转为update操作,最终delete事务持有的gap lock退化为record lock,不会造成锁范围扩大
下面用SQL Server和MySQL做测试,看一下锁的情况
SQL Server 2012
use test
go
CREATE TABLE t (
id int NOT NULL primary key,
c int DEFAULT NULL,
d int DEFAULT NULL
) CREATE NONCLUSTERED INDEX [ix_t_c] ON [dbo].[t]
(
[c] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO insert into t values(5,5,5),(10,10,10),(20,20,20),(25,25,25);
使用下面的执行顺序

在session1执行下面语句
--session 1
USE test
GO SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO begin transaction select id from t where c >10 and c <= 24 delete from t where c = 25 --commit
在session2执行下面语句
--session 2
USE test
GO SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO insert into t(id,c,d) values(27,27,27); (blocked)
申请的锁,情况如下

分析:首先我们要关注的加锁对象是二级索引【ix_t_c】,可以看到有三个range锁,这里锁住的范围是
rangeS-S(10,20]
rangeX-X(20, 25]
rangeS-U[25, +∞) 正无穷
正因为rangeS-U 锁,session 2的insert操作被阻塞了,也就是删除 c=25 这行数据,导致键范围锁扩大到 正无穷
MySQL 8.0.28
set global transaction isolation level REPEATABLE READ;
select @@global.transaction_isolation; use test; CREATE TABLE `t` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`)
) ENGINE=InnoDB; insert into t values(5,5,5),(10,10,10),(20,20,20),(25,25,25);
SQL语句执行顺序跟SQL Server一样
在session1执行下面语句
-- session 1
begin;
select id from t where c >10 and c <= 24 for update;
delete from t where c = 25; --commit
在session2执行下面语句
-- session 2
insert into t(id,c,d) values(27,27,27); (blocked)
申请的锁,情况如下
select * from performance_schema.data_locks\G
*************************** 1. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552409600:1217:140111564061632
ENGINE_TRANSACTION_ID: 7643
THREAD_ID: 331
EVENT_ID: 8
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140111564061632
LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 2. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552409600:59:5:1:140111564058528
ENGINE_TRANSACTION_ID: 7643
THREAD_ID: 331
EVENT_ID: 8
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564058528
LOCK_TYPE: RECORD
LOCK_MODE: X,INSERT_INTENTION
LOCK_STATUS: WAITING
LOCK_DATA: supremum pseudo-record
*************************** 3. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:1217:140111564055552
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: NULL
OBJECT_INSTANCE_BEGIN: 140111564055552
LOCK_TYPE: TABLE
LOCK_MODE: IX
LOCK_STATUS: GRANTED
LOCK_DATA: NULL
*************************** 4. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:5:1:140111564052496
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564052496
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: supremum pseudo-record
*************************** 5. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:5:4:140111564052496
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564052496
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: 20, 20
*************************** 6. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:5:5:140111564052496
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: c
OBJECT_INSTANCE_BEGIN: 140111564052496
LOCK_TYPE: RECORD
LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: 25, 25
*************************** 7. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:4:4:140111564052840
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140111564052840
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 20
*************************** 8. row ***************************
ENGINE: INNODB
ENGINE_LOCK_ID: 140111552408792:59:4:5:140111564052840
ENGINE_TRANSACTION_ID: 7642
THREAD_ID: 330
EVENT_ID: 12
OBJECT_SCHEMA: test
OBJECT_NAME: t
PARTITION_NAME: NULL
SUBPARTITION_NAME: NULL
INDEX_NAME: PRIMARY
OBJECT_INSTANCE_BEGIN: 140111564052840
LOCK_TYPE: RECORD
LOCK_MODE: X,REC_NOT_GAP
LOCK_STATUS: GRANTED
LOCK_DATA: 25
8 rows in set (0.00 sec)
分析:这里我们要关注的加锁对象依然是二级索引【c】,这里MySQL的情况跟SQL Server一样
LOCK_MODE: X
LOCK_STATUS: GRANTED
LOCK_DATA: supremum pseudo-record
锁住的范围是 [25, +∞) 正无穷, 所以session 2的insert操作被阻塞了,也就是删除 c=25 这行数据,导致gap lock 扩大到 正无穷
通过上面两个测试,可以知道,即使delete操作在数据表中留下了Ghost Records,但是delete事务造成的gap lock范围没有缩小为Ghost Record的 record lock
因此,阿里云内核月报中的说法有失偏颇,误导读者
本文版权归作者所有,未经作者同意不得转载。
由delete语句引起的锁范围扩大的更多相关文章
- Mysql中truncate table和delete语句的区别
Mysql中的truncate table和delete语句都可以删除表里面所有数据,但是在一些情况下有些不同! 例子: truncate table gag; (1)truncate table删除 ...
- MySQL-5.7 DELETE语句详解
1.语法 (1)单表 DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [PARTITION (partition_name [, partit ...
- 追踪SQL Server执行delete操作时候不同锁申请与释放的过程
一直以为很了解sqlserver的加锁过程,在分析一些特殊情况下的死锁之后,尤其是并发单表操作发生的死锁,对于加解锁的过程,有了一些重新的认识,之前的知识还是有一些盲区在里面的.delete加锁与解锁 ...
- 【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句
原文:[SQL Server学习笔记]Delete 语句.Output 子句.Merge语句 DELETE语句 --建表 select * into distribution from sys.obj ...
- InnoDB 中不同SQL语句设置的锁
锁定读.UPDATE 或 DELETE 通常会给在SQL语句处理过程扫描到的每个索引记录上设置记录锁.语句中是否存在排除该行的WHERE条件并不重要.InnoDB不记得确切的WHERE条件,但只知道哪 ...
- Sql Server系列:Delete语句
数据的删除将删除表的部分或全部记录,删除时可以指定删除条件从而删除一条或多条记录.如果不指定删除条件,DELETE语句将删除表中全部的记录,清空数据表. 1 DELETE语法 [ WITH <c ...
- delete语句跑了3个小时分析以及关于并行的一些知识
=====================START==================================== 闲来无事,看了下数据库跑的long running sql, SQL> ...
- SQL DELETE 语句
DELETE 语句用于删除表中的行. 语法 DELETE FROM 表名称 WHERE 列名称 = 值 Person: LastName FirstName Address City Gates Bi ...
- MySQL DELETE语句和TRUNCATE TABLE语句的区别
MySQL DELETE语句和TRUNCATE TABLE语句的区别 2010-10-08 16:05 佚名 互联网 字号:T | T 在MySQL数据库中,DELETE语句和TRUNCATE TAB ...
- 如何判断一条sql(update,delete)语句是否执行成功
如何判断一条sql(update,delete)语句是否执行成功 catch (SQLException e) { } catch不到错误应该就成功了. ============== ...
随机推荐
- CSS——组合选择器
1.后代选择器(包括儿子和孙子) .c1 .c2{ color: red; } 2.子代选择器(只选择儿子) .c3 > .c5{ color: red; } 3.与选择器 选择p标签下面的.c ...
- 解决 Https 站点请求 Http 接口服务后报 the content must be served over HTTPS 错误的问题
问题分析 之前将自己所有的 Http 站点全部更新为 Https 站点,但是在请求后台接口服务的时候还是 Http 请求,导致部署之后,直接在控制台报 This request has been bl ...
- ETL工具-nifi干货系列 第五讲 处理器GenerateFlowFile
1.今天我们一起来学习处理器GenerateFlowFile.这个处理器创建带有随机数据或自定义内容的 FlowFiles.GenerateFlowFile 对于负载测试.配置和模拟非常有用.从工具栏 ...
- 23201826-熊锋-第二次blog
一.前言 这三次pta作业第一次为答题判断程序-4,这是答题判断程序的第三次迭代,相较于答题判断三,新增了各种题型及其不同种类的答案,并且出现多选题,使得这次题目相当棘手,具有很大的挑战性.第二次为家 ...
- VIVO IQOO 5G 开关
VIVO IQOO 5G 开关 在拨号盘输入*#*#2288#*#*,然后点击网络模式选择. -
- 透过 node-exporter 彻底弄懂机器监控:01. node-exporter 框架讲解
前言 Prometheus 生态里有很多采集器负责各类监控数据的采集,其中使用最广泛的,显然是 node-exporter,负责 Linux.BSD 等系统的常规监控指标的采集,比如 CPU.内存.硬 ...
- 燕千云 YQCloud 数智化业务服务平台 发布1.12版本
2022年4月29日,燕千云 YQCloud 数智化业务服务平台发布1.12版本,优化客户服务场景.深化智能预测服务的应用,加强系统在多渠道方面的集成,全面提升企业数智化服务的能力! 作为企业数字化服 ...
- 泛型模板化设计DEMO
泛型模板化设计DEMO 1. 定义Result泛型类 package com.example.core.mydemo.java.fanxing; public class Result<T> ...
- Java验证集合空或验证对象空的方法
import java.util.ArrayList; import java.util.List; import java.util.Objects; import org.springframew ...
- Math.ceil,Math.round,Math.floor区别
Math.ceil,Math.round,Math.floor区别 //向上取整 System.out.println("amt1=" + Math.ceil(71.01)); / ...