MyRocks事务锁分析

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS Agent(兼容OpenClaw),2核4GB
RDS DuckDB + QuickBI 企业套餐,8核32GB + QuickBI 专业版
简介: # 概述 MyRocks中RocksDB作为基于快照的事务引擎,其在事务支持上有别于InnoDB,有其自身的特点。在早期的月报[[myrocks之事务处理]](http://mysql.taobao.org/monthly/2016/11/02/) 中,我们对锁的实现有过简单的分析,本文会以一些例子来介绍MyRocks是如果来加锁解锁的。 # 锁类型 MyRocks早期只支持排他锁,

概述

MyRocks中RocksDB作为基于快照的事务引擎,其在事务支持上有别于InnoDB,有其自身的特点。在早期的月报[[myrocks之事务处理]](http://mysql.taobao.org/monthly/2016/11/02/) 中,我们对锁的实现有过简单的分析,本文会以一些例子来介绍MyRocks是如果来加锁解锁的。

锁类型

MyRocks早期只支持排他锁,支持SELEC... IN SHARE MODE后,MyRocks才开始引入共享锁。

 /* Type of locking to apply to rows */
 enum { RDB_LOCK_NONE, RDB_LOCK_READ, RDB_LOCK_WRITE } m_lock_rows;

#587是关于共享锁的一个有趣BUG,有兴趣的同学可以看看。
MyRocks的锁都是内存锁,因此MyRocks事务不宜持有过多的锁,以避免占用过多的内存。
MyRocks通过参数rocksdb_max_row_locks来控制单个事务所持有锁的总数。另外,rocksdb锁系统还支持以下参数
max_num_locks:系统锁个数总限制
expiration_time:锁过期时间

如果锁个数超出限制,客户端会返回下面的错误

failed: 12054: Status error 10 received from RocksDB: Operation aborted: Failed to acquire lock due to max_num_locks limit

隔离级别

MyRocks的事务隔离级只支持的READ-COMMITED和REPEATABLE-READ。隔离级别的支持和snapshot密切相关,隔离级别为READ-COMMITED时,事务中每的个stmt都会建立一个snapshot, 隔离级别为REPEATABLE-REA时,只在事务开启后第一个stmt建立一次snapshot。MyRocks中隔离级别不同不会影响加锁和解锁的行为,因此,后面在分析MyRocks的加锁解锁时不区分隔离级别。

隐式主键

MyRocks支持创建无主键的表,但RocksDB作为KV存储,是需要KEY的。因此,RocksDB内部会给表增加一个名为"HIDDEN_PK_ID"的隐式主键列,此值自增,类似与自增列。此列对于MySQL server层是透明的,读取表数据时会自动跳过"HIDDEN_PK_ID"列。

对于无主键的表,MyRocks的锁都是加在隐式主键上的。

对于binlog复制来说,MyRocks隐式主键并不会提升复制速度,因为隐式主键对server层是透明的,主键列不会记入binlog。
因此,建议MyRocks表都指定主键。

加锁分析

以此表结构来分析各类语句的加锁情况。

create table t1(id int primary key, c1 int unique, c2 int, c3 int, key idx_c2(c2)) engine=rocksdb;
insert into t1 values(1,1,1,1);
insert into t1 values(2,2,2,2);
insert into t1 values(3,3,3,3);
insert into t1 values(4,4,4,4);
  • 示例 select
select * from t1;

MVCC, 普通读不加锁

  • 示例 select .. in share mode
select * from t1 where id=1 in share mode;

对主键id=1记录加S锁

  • 示例 select .. for update
select * from t1 where id=1 for update;

对主键id=1记录加X锁

  • 示例 insert
begin;
insert into t1 values(1,1,1,1);
rollback;

主键id=1加X锁
唯一索引c1=1加X锁

  • 示例 delete by主键
begin;
delete from t1 where id=1;
rollback;

主键id=1加X锁

  • 示例 delete by唯一索引
begin;
delete from t1 where c1=2;
rollback;

主键id=2加X锁,其他索引不加锁

  • 示例 delete by普通索引
begin;
delete from t1 where c2=3;
rollback;

主键id=3加X锁,其他索引不加锁

  • 示例 delete by无索引
begin;
delete from t1 where c3=4;
rollback;

对主键每条加X锁,其他索引不加锁
实际上server层过滤不符合条件的行会释放锁,最终只对主键id=4加X锁

  • 示例 delete by 主键不存在的行
begin;
delete from t1 where id=100;
rollback;

主键id=100加X锁

  • 示例 delete by 其他索引不存在的行
begin;
delete from t1 where c1=100;
rollback;

没有锁可以加

以上例子基本可以覆盖所有加锁的情况,再举例几个例子练习下

  • 示例 select for update
begin;
select * from t1 where  c2=3 for update;
rollback;

主键id=3加X锁, 其他索引不加锁

  • 示例 update更新无索引列
begin;
update t1 set c3=5 where c3=4;
rollback;

对主键每条加X锁,其他索引不加锁
实际上server层过滤不符合条件的行会释放锁,最终只对主键id=4加X锁

  • 示例 update更新索引列
begin;
update t1 set c2=5 where c3=4;
rollback;

对主键每条加X锁,其他索引不加锁
实际上server层过滤不符合条件的行会释放锁,最终只对主键id=4加X锁
同时会对唯一索引c2=5加X锁

对于无主键表的表说,RocksDB内部会有隐式主键,所加锁都在隐式主键上

解锁

事务提交或回滚时都会将事务所持有的锁都释放掉。
另外一种情况是,对于不满足查询条件的记录,MySQL会提前释放锁。

总结

  • MyRocks只会对主键和唯一索引加锁,普通索引不会加锁。
  • 只有插入或更新了唯一索引时,才会对唯一索引加锁,对唯一索引加锁的目的是为了保证唯一性。
  • 按主键锁定查找不存在的行时,会对不存在的行主键加X锁。
  • 按二级索引查找时,只会对主键加锁,不会对二级锁引加锁。
  • S锁只应用于SELECT ... IN SHARE MODE语句。

堆栈

最后提供一些堆栈信息,方便学习

  • 走唯一索引对主键加锁
#0  rocksdb::TransactionLockMgr::TryLock
#1  rocksdb::PessimisticTransactionDB::TryLock
#2  rocksdb::PessimisticTransaction::TryLock
#3  rocksdb::TransactionBaseImpl::GetForUpdate
#4  myrocks::Rdb_transaction_impl::get_for_update
#5  myrocks::ha_rocksdb::get_for_update
#6  myrocks::ha_rocksdb::get_row_by_rowid
#7  get_row_by_rowid
#8  myrocks::ha_rocksdb::read_row_from_secondary_key
#9  myrocks::ha_rocksdb::index_read_map_impl
#10 myrocks::ha_rocksdb::read_range_first
#11 handler::multi_range_read_next
#12 QUICK_RANGE_SELECT::get_next
#13 rr_quick
#14 mysql_delete
#15 mysql_execute_command
#16 mysql_parse
#17 dispatch_command
  • 提交时解锁
#0  rocksdb::TransactionLockMgr::UnLockKey
#1  rocksdb::TransactionLockMgr::UnLock
#2  rocksdb::PessimisticTransactionDB::UnLock
#3  rocksdb::PessimisticTransaction::Clear
#4  rocksdb::PessimisticTransaction::Commit
#5  myrocks::Rdb_transaction_impl::commit_no_binlog
#6  commit
#7  myrocks::rocksdb_commit
#8  ha_commit_low
#9  TC_LOG_DUMMY::commit
#10 ha_commit_trans
#11 trans_commit
#12 mysql_execute_command
#13 mysql_parse
#14 dispatch_command
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
开发工具 git
如何在vscode编辑器中实时查看代码git记录(被谁修改、自己什么时候修改)
如何在vscode编辑器中实时查看代码git记录(被谁修改、自己什么时候修改)
8106 0
如何在vscode编辑器中实时查看代码git记录(被谁修改、自己什么时候修改)
|
存储 算法 关系型数据库
Ceph介绍及原理架构分享
Ceph介绍及原理架构分享
933 0
|
关系型数据库 MySQL 数据库
MySQL Innodb Purge简介
前言 为什么MySQL InnoDB需要Purge操作?明确这个问题的答案,首先还得从InnoDB的并发机制开始。为了更好的支持并发,InnoDB的多版本一致性读是采用了基于回滚段的的方式。另外,对于更新和删除操作,InnoDB并不是真正的删除原来的记录,而是设置记录的delete mark为1。
9535 1
|
Oracle 数据库 关系型数据库
深入详解Oracle data change notification
深入详解 Oracle data change notification
1969 0
|
SQL 移动开发 算法
MySQL 8.0.23 Hypergraph Join Optimizer代码详解
MySQL Join MySQL本身没有常规意义上的执行计划,一般情况就是通过JOIN和QEP_TAB这两个结构组成。QEP_TAB 的全称是Query Execution Plan Table,这个“Table“可以是物理表、内存表、常量表、子查询的结果表等等。作为整个单独JOIN执行计划载体之前还承担着整个执行路径的调用和流转,但是从8.0.20后,全面的生成了独立的
2052 0
MySQL 8.0.23 Hypergraph Join Optimizer代码详解
|
存储 SQL 运维
Hologres OLAP场景核心能力介绍-2024实时数仓Hologres线上公开课02
本次分享由Hologres产品经理赵红梅(梅酱)介绍Hologres在OLAP场景中的核心能力。内容涵盖OLAP场景的痛点、Hologres的核心优势及其解决方法,包括实时数仓分析、湖仓一体加速、丰富的索引和查询性能优化等。此外,还介绍了Hologres在兼容PG生态、支持多种BI工具以及高级企业级功能如计算组隔离和serverless computing等方面的优势。最后通过小红书和乐元素两个典型客户案例,展示了Hologres在实际应用中的显著效益,如运维成本降低、查询性能提升及成本节省等。
508 7
|
XML JavaScript Java
【JAVA XML 探秘】DOM、SAX、StAX:揭秘 Java 中 XML 解析技术的终极指南!
【8月更文挑战第25天】本文详细探讨了Java中三种主流的XML解析技术:DOM、SAX与StAX。DOM将XML文档转换为树状结构,便于全方位访问和修改;SAX采取事件驱动模式,适用于大型文件的顺序处理;StAX则兼具DOM和SAX的优点,支持流式处理和随机访问。文中提供了每种技术的示例代码,帮助读者理解如何在实际项目中应用这些解析方法。
769 1
|
机器人 应用服务中间件 API
轻松集成私有化部署Dify文本生成型应用
Dify 是一款开源的大语言模型应用开发平台,融合了后端即服务(Backend as Service)和 LLMOps 的理念,使开发者能快速搭建生产级生成式 AI 应用。通过阿里云计算巢,用户可以一键部署 Dify 社区版,享受独享的计算和网络资源,并无代码完成钉钉、企业微信等平台的应用集成。本文将详细介绍如何部署 Dify 并将其集成到钉钉群聊机器人和企业微信中,帮助您轻松实现 AI 应用的定义与数据运营,提升工作效率。
5911 65
轻松集成私有化部署Dify文本生成型应用
|
KVM 虚拟化 数据安全/隐私保护
KVM虚拟机安装实战
本文讲述了如何创建并使用VNC连接KVM虚拟机的详细教程,包括安装图解和命令行参数说明。
668 8
|
存储
硬盘数据恢复—硬盘出现物理坏道如何妙手回春?
硬盘故障: 硬盘存在物理坏道。 硬盘存在物理坏道的典型表现: 1、若硬盘为系统盘,故障表现通常为:操作系统异常缓慢、蓝屏,重启系统后引导失败并报告硬盘读取出错、系统自动反复重启。 2、若硬盘为移动硬盘,故障表现通常为:电脑无法加载盘符、提示硬盘需要格式化、频繁提示需要运行chkdsk来检查和修复磁盘、数据读取缓慢、死机。