由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语句引起的锁范围扩大的更多相关文章

  1. Mysql中truncate table和delete语句的区别

    Mysql中的truncate table和delete语句都可以删除表里面所有数据,但是在一些情况下有些不同! 例子: truncate table gag; (1)truncate table删除 ...

  2. MySQL-5.7 DELETE语句详解

    1.语法 (1)单表 DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [PARTITION (partition_name [, partit ...

  3. 追踪SQL Server执行delete操作时候不同锁申请与释放的过程

    一直以为很了解sqlserver的加锁过程,在分析一些特殊情况下的死锁之后,尤其是并发单表操作发生的死锁,对于加解锁的过程,有了一些重新的认识,之前的知识还是有一些盲区在里面的.delete加锁与解锁 ...

  4. 【SQL Server学习笔记】Delete 语句、Output 子句、Merge语句

    原文:[SQL Server学习笔记]Delete 语句.Output 子句.Merge语句 DELETE语句 --建表 select * into distribution from sys.obj ...

  5. InnoDB 中不同SQL语句设置的锁

    锁定读.UPDATE 或 DELETE 通常会给在SQL语句处理过程扫描到的每个索引记录上设置记录锁.语句中是否存在排除该行的WHERE条件并不重要.InnoDB不记得确切的WHERE条件,但只知道哪 ...

  6. Sql Server系列:Delete语句

    数据的删除将删除表的部分或全部记录,删除时可以指定删除条件从而删除一条或多条记录.如果不指定删除条件,DELETE语句将删除表中全部的记录,清空数据表. 1 DELETE语法 [ WITH <c ...

  7. delete语句跑了3个小时分析以及关于并行的一些知识

    =====================START==================================== 闲来无事,看了下数据库跑的long running sql, SQL> ...

  8. SQL DELETE 语句

    DELETE 语句用于删除表中的行. 语法 DELETE FROM 表名称 WHERE 列名称 = 值 Person: LastName FirstName Address City Gates Bi ...

  9. MySQL DELETE语句和TRUNCATE TABLE语句的区别

    MySQL DELETE语句和TRUNCATE TABLE语句的区别 2010-10-08 16:05 佚名 互联网 字号:T | T 在MySQL数据库中,DELETE语句和TRUNCATE TAB ...

  10. 如何判断一条sql(update,delete)语句是否执行成功

    如何判断一条sql(update,delete)语句是否执行成功 catch  (SQLException    e)  {  }  catch不到错误应该就成功了.   ============== ...

随机推荐

  1. c#动态执行脚本的3种方式详解

    1.使用Roslyn编译器 2.使用IronPython或IronRuby 3.使用JavaScript引擎 在C#中,可以使用一些第三方库或内置类库实现动态执行脚本的功能.以下是几个常用的方案: 1 ...

  2. ReplayKit2 采集音视频回调格式

    一.音频 ReplayKit2 RPSampleBufferTypeAudioApp sampleBuffer = CMSampleBuffer 0x100500c50 retainCount: 1 ...

  3. 网页CSS源码

    EntryTag { margin-top:20px; font-size:9pt; color:gray } .topicListFooter { text-align:right; margin- ...

  4. Redis单线程

    Redis是基于Reactor模式开发的网络事件处理器,这个处理器是单线程的,所 以redis是单线程的. 为什么它是单线程还那么快呢? 主要有以下几个原因: 一.纯内存操作 由于Redis是纯内存操 ...

  5. 利用QEMU模拟大端序机器

    简介 当前我们安装虚拟机,一般小端机器比较多,有时候想模拟大端机器测试程序,这时就有模拟大端机器的需求. 参考:利用 QEMU USER 模式运行 mips 程序 - sinpo828 - 博客园 ( ...

  6. c#使用webView2 访问本地静态html资源跨域Cors问题 (附带代理服务helper帮助类)

    背景 在浏览器中访问本地静态资源html网页时,可能会遇到跨域问题如图. 是因为浏览器默认启用了同源策略,即只允许加载与当前网页具有相同源(协议.域名和端口)的内容. WebView2默认情况下启用了 ...

  7. web游览器的标签页仿 ios mac 苹果的墓碑机制 (js代码)

    背景: 本来项目开发系统防挂机功能,在其余游览器中均可以使用.但是呢在苹果的safair游览器中会出现几率失效,最后经过排查发现是苹果的墓碑机制导致.即:此标签页活跃,其他标签页假死.然后就导致防挂机 ...

  8. 原来Stable Diffusion是这样工作的

    stable diffusion是一种潜在扩散模型,可以从文本生成人工智能图像.为什么叫做潜在扩散模型呢?这是因为与在高维图像空间中操作不同,它首先将图像压缩到潜在空间中,然后再进行操作. 在这篇文章 ...

  9. disabled 和 readonly 都是 HTML 表单元素的属性,它们有一些相同点和不同点。

    disabled 和 readonly 都是 HTML 表单元素的属性,它们有一些相同点和不同点. 相同点: disabled 和 readonly 属性都可以用于表单中的输入框.文本域等元素,用于控 ...

  10. 微信支付or支付宝支付调用流程图

    微信支付or支付宝支付调用流程图 支付宝小程序支付调用流程https://opendocs.alipay.com/mini/03l735 微信H5支付调用流程https://pay.weixin.qq ...