Rocksdb事务隔离性指的是多线程并发事务使用时候,事务与事务之间的隔离性,通过加锁机制来实现,本文重点剖析Read Commited隔离级别下,Rocksdb的加锁机制。

  1. Rocksdb事务相关类族

Rocksdb的事务相关的类图如下图所示。主要有两个类族,Transaction和DB,默认采用PessimisticTransaction,而PessimisticTransaction内部的加锁机制通过TransactionLockMgr来实现的。

TransactionLockMgr内部维护了LockMap。TransactionLockMgr根据每个记录的Key计算hash值,再对num_stripes取模,在LockMap中的向量Std::vector<LockMapStripe>定位LockMapStripe,这样减少实体锁的竞争激烈程度,相当于锁分解。

LockMap的数据成员如下

Size_t num_stripes          LockMapStripe个数,默认16个

Std::vector<LockMapStripe>   LockMapStripe数组

LockMapStripe的数据成员如下

std::shared_ptr<TransactionDBMutex>  stripe_mutex :   实体锁

std::shared_ptr<TransactionDBCondVar>  stripe_cv :     实体条件变量

std::unordered_map<std::string, LockInfo>  keys :       具有相同Key hash值的每条记录的加锁信息,std::string为记录的Key值。

LockInfo的数据成员如下

bool exclusive :                     排它锁,还是共享锁

uint64_t expiration_time :            锁的过期时间

autovector<TransactionID>  txn_ids :   这把锁阻塞的事务ID列表

2. Rocksdb事务流程分析

上述流程,是应用创建TransactionDB,然后Put一条记录,再Commit的协作流程图,在Put阶段调用TransactionLockMgr的TryLock方法,Commit阶段调用TransactionLockMgr的UnLock方法。

TransactionLockMgr::TryLock内部的主要逻辑在AcquireLocked函数中,TransactionLockMgr::UnLock内部的主要逻辑在UnlockKey函数中,下面具体分析这两个函数。绿色部分字体为个人注解。

AcquireLocked

Status TransactionLockMgr::AcquireLocked(LockMap* lock_map,

LockMapStripe* stripe,

const std::string& key,    //记录的Key值

Env* env,

LockInfo&& txn_lock_info,  //当前事务锁信息

uint64_t* expire_time,     //锁的过期时间

autovector<TransactionID>* txn_ids)

{

Status result;

auto stripe_iter = stripe->keys.find(key);  // 检查这条记录的Key是否已经被加锁了。

if (stripe_iter != stripe->keys.end()) {       // 这条记录的Key已经被之前事务加过锁

LockInfo& lock_info = stripe_iter->second;

if (lock_info.exclusive || txn_lock_info.exclusive) {   //之前事务或者当前事务加的是排他锁,

if (lock_info.txn_ids.size() == 1 &&

lock_info.txn_ids[0] == txn_lock_info.txn_ids[0]) {  //之前加锁的事务就是当前事务

lock_info.exclusive = txn_lock_info.exclusive;

lock_info.expiration_time = txn_lock_info.expiration_time;

} else {       //之前加锁的事务不是当前事务

if (IsLockExpired(txn_lock_info.txn_ids[0], lock_info, env,

expire_time)) {   // 之前事务加的锁已经过期,可以清除

lock_info.txn_ids = txn_lock_info.txn_ids;

lock_info.exclusive = txn_lock_info.exclusive;

lock_info.expiration_time = txn_lock_info.expiration_time;

} else {

result = Status::TimedOut(Status::SubCode::kLockTimeout);

*txn_ids = lock_info.txn_ids;   // 返回之前事务列表

}

}

} else {   //当前事务加的是共享锁

lock_info.txn_ids.push_back(txn_lock_info.txn_ids[0]);

lock_info.expiration_time =

std::max(lock_info.expiration_time, txn_lock_info.expiration_time);

}

} else {  // 这条记录的Key没有被之前事务加过锁

if (max_num_locks_ > 0 &&

lock_map->lock_cnt.load(std::memory_order_acquire) >= max_num_locks_) {

result = Status::Busy(Status::SubCode::kLockLimit);

} else {

// 当前事务执行加锁操作

stripe->keys.emplace(key, std::move(txn_lock_info));

if (max_num_locks_) {

lock_map->lock_cnt++;

}

}

}

return result;

}

UnlockKey逻辑相对简单一些,主要是删除加锁的记录,并且唤醒被阻塞的事务。

void TransactionLockMgr::UnLockKey(const PessimisticTransaction* txn,

const std::string& key,

LockMapStripe* stripe, LockMap* lock_map,

Env* env) {

TransactionID txn_id = txn->GetID();

auto stripe_iter = stripe->keys.find(key);

if (stripe_iter != stripe->keys.end()) {

auto& txns = stripe_iter->second.txn_ids;

auto txn_it = std::find(txns.begin(), txns.end(), txn_id);

// Found the key we locked.  unlock it.

if (txn_it != txns.end()) {

if (txns.size() == 1) {

stripe->keys.erase(stripe_iter);

} else {

auto last_it = txns.end() - 1;

if (txn_it != last_it) {

*txn_it = *last_it;

}

txns.pop_back();

}

if (max_num_locks_ > 0) {

// Maintain lock count if there is a limit on the number of locks.

assert(lock_map->lock_cnt.load(std::memory_order_relaxed) > 0);

lock_map->lock_cnt--;

}

}

} else {

// This key is either not locked or locked by someone else.  This should

// only happen if the unlocking transaction has expired.

assert(txn->GetExpirationTime() > 0 &&

txn->GetExpirationTime() < env->NowMicros());

}

}

RocksDB事务的隔离性分析【原创】的更多相关文章

  1. MySQL:事务的隔离性

    [参考文章]:数据库的事务特性及隔离级别 1. 事务的四大特性 1.1 原子性(Atomicity) 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用 ...

  2. 一文搞懂MySQL事务的隔离性如何实现|MVCC

    关注公众号[程序员白泽],带你走进一个不一样的程序员/学生党 前言 MySQL有ACID四大特性,本文着重讲解MySQL不同事务之间的隔离性的概念,以及MySQL如何实现隔离性.下面先罗列一下MySQ ...

  3. Mysql学习之事务的隔离性

    今天咱们说说事务,相信大家都知道事务的 ACID (Atomicity.Consistency.Isolation.Durability,即原子性.一致性.隔离性.持久性). 原子性:表示一个事务不可 ...

  4. Spring 事务机制详解(事务的隔离性和传播性)

    原文出处: 陶邦仁 Spring事务机制主要包括声明式事务和编程式事务,此处侧重讲解声明式事务,编程式事务在实际开发中得不到广泛使用,仅供学习参考. Spring声明式事务让我们从复杂的事务处理中得到 ...

  5. 具体问题:Spring 事务的隔离性,并说说每个隔离性的区别

    使用步骤: 步骤一.在spring配置文件中引入<tx:>命名空间<beans xmlns="http://www.springframework.org/schema/b ...

  6. 事务四大特征:原子性,一致性,隔离性和持久性(ACID)

    一.事务 定义:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位. 准备工作:为了说明事务的ACID原理,我们使用银行账户及资金管理的案例进行分析. [sql] ...

  7. 跟面试官侃半小时MySQL事务隔离性,从基本概念深入到实现

    提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consiste ...

  8. 事务传播性、隔离性与MVCC

    一.事务传播性 1.1 什么是事务的传播性 事务的传播性一般在事务嵌套时候使用,比如在事务A里面调用了另外一个使用事务的方法,那么这俩个事务是各自作为独立的事务执行提交,还是内层的事务合并到外层的事务 ...

  9. 事务ACID特性,其中I代表隔离性(Isolation)。

    事务ACID特性,其中I代表隔离性(Isolation). 什么是事务的隔离性? 隔离性是指,多个用户的并发事务访问同一个数据库时,一个用户的事务不应该被其他用户的事务干扰,多个并发事务之间要相互隔离 ...

随机推荐

  1. SpringCloud(二)- Consul介绍、安装、使用

    唯能极于情,故能极于剑有问题或错误请及时联系小编或关注小编公众号 “CodeCow”,小编一定及时回复和改正,期待和大家一起学习交流 此文由四部分组成(Consul简介.安装.实操.总结),别着急,慢 ...

  2. This关键字练习

    Account: package com.aff.ex; public class Account { private int id;// 账号 private double balance;// 余 ...

  3. JS代码静态分析及挖掘

    JavaScript 已经成为现代 Web 浏览器开发中最普遍的技术之一.使用客户端 JavaScript 框架(如 AngularJS,ReactJS 和 Vue.js)构建的应用程序已向前端输送了 ...

  4. tomcat漏洞利用总结

    一.后台war包getshell 漏洞利用: tomcat在conf/tomcat-users.xml配置用户权限 <?xml version="1.0" encoding= ...

  5. Beta冲刺 —— 6.1

    这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.讨论并解决每个人存在的问 ...

  6. jchdl - RTL实例 - Adder4Carry

    https://mp.weixin.qq.com/s/j4zLmjKgau2vRXVNfm0SIA   带进位的加法.   参考链接 https://github.com/wjcdx/jchdl/bl ...

  7. 我一个二本大学是如何拿到阿里offer的

    作者:薛勤,互联网从业者,编程爱好者. 本文首发自公众号:代码艺术(ID:onblog)未经许可,不可转载 01:终于步入大学 我既没有跨过山和大海,也没有穿过人山人海,我就是我,一个普通本科大学生. ...

  8. Multiple annotations found at this line:- The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path

    解决办法: 右键所在项目 build path configure build path java build path Add Library server Run time (Apache Tom ...

  9. Java实现 蓝桥杯VIP 算法训练 无权最长链

    试题 算法训练 无权最长链 问题描述 给定一个n节点m边的无圈且连通的图,求直径 输入格式 第一行两个数字n,m 接下来m行每行两个数字x,y,代表x,y之间有一条边 输出格式 要求用户的输出满足的格 ...

  10. 第三届蓝桥杯JavaC组国(决)赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1. 填算式 [结果填空] (满分11分) 看这个算式: ☆☆☆ + ☆☆☆ = ☆☆☆ 如果每个五角星代表 1 ~ 9 的不同的数字. ...