MyRocks事务锁分析-阿里云开发者社区

开发者社区> zysql> 正文

MyRocks事务锁分析

简介: # 概述 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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
数据分析实战 基于EXCEL和SPSS系列工具的实践》一1.4 数据分析的流程
数据分析一般有数据采集、数据整理、制表、数据分析、数据呈现等多个阶段。当然,不是说每一个数据分析的过程都需要这些阶段,有的企业数据质量非常好,自然就不需要数据采集过程了;也有些数据分析并不怎么需要呈现过程。不过,为了方便读者理解,下面将介绍一个完整的流程。
1384 0
Fescar&Seata分布式事务实现原理解析探秘
前言 fescar发布已有时日,分布式事务一直是业界备受关注的领域,fescar发布一个月左右便受到了近5000个star足以说明其热度。当然,在fescar出来之前,已经有比较成熟的分布式事务的解决方案开源了,比较典型的方案如LCN(https://github.com/codingapi/tx-lcn)的2pc型无侵入事务,目前lcn已发展到5.0,已支持和fescar事务模型类似的TCX型事务。
1923 0
MyRocks写入分析
--- title: MySQL · myrocks · myrocks写入分析 author: 张远 --- # 写入流程 myrocks的写入流程可以简单的分为以下几步来完成 1. 将解析后的记录(kTypeValue/kTypeDeletion)写入到WriteBatch中 2. 将WAL日志写入log文件 3. 将WriteBatch中的内容写到memtabl
7383 0
《问卷数据分析——破解SPSS的六类分析思路》| 每日读本书
从问卷的设计调研到六类问卷分析思路和方法的应用,专注、详细,深入浅出。每日搜罗最具权威专业书籍,更多图书请关注“每日读本书”。
1624 0
vacuum freeze无法回收事务号问题分析
vacuum freeze报错问题分析
2981 0
Apache Spark Delta Lake 事务日志实现源码分析
Apache Spark Delta Lake 事务日志实现源码分析 我们已经在这篇文章详细介绍了 Apache Spark Delta Lake 的事务日志是什么、主要用途以及如何工作的。那篇文章已经可以很好地给大家介绍 Delta Lake 的内部工作原理,原子性保证,本文为了学习的目的,带领大家从源码级别来看看 Delta Lake 事务日志的实现。
1608 0
分布式事务解决方案——柔性事务与服务模式
原创: Hollis 在我的博客中,介绍过很多关于分布式和事务的文章,在阅读本文之前,希望读者可以对这些基础知识有所了解,这里简单把之前的文章列举下,已经按照顺序排好,可按顺序阅读。
1613 0
PostgreSQL的事务隔离分析
隔离级别(Isolation levels) 有四种隔离级别: 可序列化(Serializable) 可重复读(Repeatable reads) 提交读(Read committed) 未提交读(Read uncommitted) ...
2341 0
事务模板 VS 声明式事务
本文比较声明式事务与事务模板的优缺点。
1223 0
oracle一个事务的完整流程分析
oracle服务进程如何处理用户进程的请求服务器进程在完成用户进程的请求过程中,主要完成如下7个任务:0.sql语句的解析1.数据块的读入db buffer2.记日志3.为事务建立回滚段4.
659 0
+关注
zysql
张远 MySQL/MyRocks
34
文章
10
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载