MySQL 主键索引等值查询加什么锁?
这一期介绍读已提交、可重复读两个隔离级别下,主键索引等值查询的加锁情况。
> 作者:操盛春,爱可生技术专家,公众号『一树一溪』作者,专注于研究 MySQL 和 OceanBase 源码。 > 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
> 本文基于 MySQL 8.0.32 源码,存储引擎为 InnoDB。
1. 准备工作
创建测试表:
CREATE TABLE `t1` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `i1` int DEFAULT '0', PRIMARY KEY (`id`) USING BTREE, KEY `idx_i1` (`i1`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
插入测试数据:
INSERT INTO `t1` (`id`, `i1`) VALUES (10, 101), (20, 201), (30, 301), (40, 401);
2. 可重复读
把事务隔离级别设置为 REPEATABLE-READ(如已设置,忽略此步骤):
SET transaction_isolation = 'REPEATABLE-READ'; -- 确认设置成功 SHOW VARIABLES like 'transaction_isolation'; +-----------------------+-----------------+ | Variable_name | Value | +-----------------------+-----------------+ | transaction_isolation | REPEATABLE-READ | +-----------------------+-----------------+
执行以下 select 语句:
begin; select * from t1 where id = 10 for share;
查看加锁情况:
select engine_transaction_id, object_name, index_name, lock_type, lock_mode, lock_status, lock_data from performance_schema.data_locks where object_name = 't1' and lock_type = 'RECORD'\G ***************************[ 1. row ]*************************** engine_transaction_id | 281479856983976 object_name | t1 index_name | PRIMARY lock_type | RECORD lock_mode | S,REC_NOT_GAP lock_status | GRANTED lock_data | 10
lock_data = 10, lock_mode = S,REC_NOT_GAP 表示对主键索引中 <id = 10> 的记录加了共享普通记录锁。
可重复读隔离级别下:
- 对于 select 语句中 where 条件覆盖范围内的记录,默认加共享 Next-Key 锁。
- 对于 update、delete 语句中 where 条件覆盖范围内的记录,默认加排他 Next-Key 锁。
上面的 select 语句却对 <id = 10> 的记录加了共享普通记录锁,这是为什么呢?
这就要从可重复读隔离级别的特点说起了。可重复读隔离级别下,同一个事务多次执行同一条 select 语句能够读取到数量和内容都完全相同的记录。
可重复读隔离级别下,对 where 条件覆盖范围内的记录默认加 Next-Key 锁,既锁住索引记录本身,防止其它事务修改或者删除记录,又锁定索引记录前面的间隙,防止其它事务往间隙中插入记录。
示例 SQL 的 where 条件中只包含主键索引字段,主键索引的唯一约束能够保证:只要不删除表中 <id = 10> 的记录,就不会再有其它 <id = 10> 的记录插入到主键索引中。
这种情况下,只需要对 select 语句中 where 条件对应的这条记录加普通记录锁,防止其它事务修改这条记录,就能保证可重复读。
3. 读已提交
把事务隔离级别设置为 READ-COMMITTED(如已设置,忽略此步骤):
SET transaction_isolation = 'READ-COMMITTED'; -- 确认设置成功 SHOW VARIABLES like 'transaction_isolation'; +-----------------------+----------------+ | Variable_name | Value | +-----------------------+----------------+ | transaction_isolation | READ-COMMITTED | +-----------------------+----------------+
执行以下 select 语句:
begin; select * from t1 where id = 10 for share;
查看加锁情况:
select engine_transaction_id, object_name, index_name, lock_type, lock_mode, lock_status, lock_data from performance_schema.data_locks where object_name = 't1' and lock_type = 'RECORD'\G ***************************[ 1. row ]*************************** engine_transaction_id | 281479856983976 object_name | t1 index_name | PRIMARY lock_type | RECORD lock_mode | S,REC_NOT_GAP lock_status | GRANTED lock_data | 10
lock_data = 10, lock_mode = S,REC_NOT_GAP 表示对主键索引中 <id = 10> 的记录加了共享普通记录锁。
读已提交隔离级别下:
- 对于 select 语句中 where 条件覆盖范围内的记录,默认加共享普通记录锁。
- 对于 update、delete 语句中 where 条件覆盖范围内的记录,默认加排他普通记录锁。
示例 SQL 执行过程中,对主键索引中 <id = 10> 的记录加共享普通记录锁,属于默认情况,不需要其它解释了。
4. 总结
可重复读、读已提交两种隔离级别下,对主键索引字段进行等值查询,虽然都对记录加了共享普通记录锁,但是它们的加锁逻辑是不一样的。
这两种隔离级别下,对唯一索引进行等值查询,加锁情况是什么样的呢?
欢迎大家在评论区留言交流。
更多技术文章,请访问:https://opensource.actionsky.com/
关于 SQLE
SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。
✨ Github:https://github.com/actiontech/sqle
📚 文档:https://actiontech.github.io/sqle-docs/
💻 官网:https://opensource.actionsky.com/sqle/
👥 微信群:请添加小助手加入 ActionOpenSource
🔗 商业支持:https://www.actionsky.com/sqle</id></id></id></id></id></id>

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
程序员的匆匆岁月,下一阶段是?
为了迎接 1024 程序员节,OSChina 开源中国新增了【家里有个程序员】栏目,记录一下 OSCer 们当前的生活,欢迎各位 OSCer 踊跃投稿呀。 投稿细则:https://my.oschina.net/u/3859945/blog/15727245 入这行已经十年了,我是师范类的计算机专业,同学也多数入行了教师职业,这也是毕业时我艰难择业的原因之一。 是稳妥地做一名教师,还是继续在计算机专业上深耕,让我纠结了很久。直到我考上了教师,踏入了校门,才发现自己还是喜欢在外面工作。至于为什么要考上了才发现,可能是心理作祟,就像一些水果,看着艳丽,吃到嘴里却不是自己憧憬的味道。最终我向教育局提交了辞职申请。 来到深圳找工作也并不顺利,并没有进入到我理想的企业,但我没有后悔辞职,相信可以慢慢积累、提高,找到理想的工作。好在那时年少,一切都不晚,没有因为前途的迷雾而退却。现在感觉做一切事情都需要好的心性,错过了正确的年纪才是最可怕的。 来到这家做仓储物流的公司后,我的编程生涯进入了正轨。那些年的双十一真是火爆啊,我们这些不爱购物的程序员们必须跟着熬夜,确保系统的正常使用。如果出一点...
- 下一篇
快手:从 Clickhouse 到 Apache Doris, 实现湖仓分离向湖仓一体架构升级
导读:快手 OLAP 系统为内外多个场景提供数据服务,每天承载近 10 亿的查询请求。原有湖仓分离架构,由离线数据湖和实时数仓组成,面临存储冗余、资源抢占、治理复杂、查询调优难等问题。通过引入 Apache Doris 湖仓一体能力,替换了 Clickhouse ,升级为湖仓一体架构,并结合 Doris 的物化视图改写能力和自动物化服务,实现高性能的数据查询以及灵活的数据治理。 作者|快手大数据架构师 李振炜、曾斯维、周思闽 在当今这个数据洪流的信息时代下,数据已跃升为企业不可或缺的核心资产。深度挖掘并提炼数据内在价值,成为支撑企业战略决策的重要依据。在此背景下,快手建立了 OLAP 系统,该系统在快手应用极为广泛,每天承载近 10 亿的查询请求,为内外多个业务场景提供数据服务。具体场景包括: ToB 系统:商业化报表引擎、商业化 DMP、商业化磁力金牛、电商选品等 内部系统:KwaiBI、春节/活动大屏、APP 分析、数据同步、用户理解中心、APM、CDN 监控、雷达监控系统等 存在的问题 最初,快手 OLAP 系统整体技术架构由离线数据湖和实时数仓这两部分组成,离线数据湖核心引擎为...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2全家桶,快速入门学习开发网站教程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS6,CentOS7官方镜像安装Oracle11G