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
相關文章
- InnoDB 事務加鎖分析
- 十、Redis事務、事務鎖Redis
- MySQL事務與鎖MySql
- MySQL 事務和鎖MySql
- MySQL事務和鎖MySql
- MySql 三大知識點,索引、鎖、事務,原理分析MySql索引
- MS SQL Server資料庫事務鎖機制分析(轉)SQLServer資料庫
- MySQL 筆記 - 事務&鎖MySql筆記
- mysql之鎖與事務MySql
- redis-19.事務-鎖Redis
- 關於資料庫事務和鎖的一些分析資料庫
- 一次ORACLE分散式事務鎖異常處理分析Oracle分散式
- etcd分散式鎖及事務分散式
- MySQL入門--事務與鎖MySql
- mysql鎖與事務總結MySql
- Redis的事務、樂觀鎖和悲觀鎖Redis
- MySQL在預設事務下各SQL語句使用的鎖分析MySql
- 深入理解Redis事務、事務異常、樂觀鎖、管道Redis
- spring事務管理原始碼分析(二)事務處理流程分析Spring原始碼
- 分散式鎖和spring事務管理分散式Spring
- redis(10)事務和鎖機制Redis
- mysql 事務,鎖,隔離機制MySql
- 事務隔離(二):基於加鎖方式的事務隔離原理
- MySQL – 事務的啟動 / 設定 / 鎖 / 解鎖——入門MySql
- MySQL 核心三劍客 —— 索引、鎖、事務MySql索引
- SpringCloud Alibaba(六) - Seata 分散式事務鎖SpringGCCloud分散式
- mysql事務隔離級別和鎖MySql
- mysql事務處理與鎖機制MySql
- Mysql鎖與事務隔離級別MySql
- mysql同一個事務中update,insert導致死鎖問題分析解決MySql
- Sql Server 資料庫事務與鎖,同一事務更新又查詢鎖?期望大家來解惑SQLServer資料庫
- Laravel 事務中 使用 悲觀鎖 小結Laravel
- MySql 三大知識點——索引、鎖、事務!MySql索引
- 分散式事務鎖模式之一:租用Lease分散式模式
- MySQL(一):MySQL資料庫事務與鎖MySql資料庫
- MySQL中的事務原理和鎖機制MySql
- 實現宣告式鎖,支援分散式鎖自定義鎖、SpEL和結合事務分散式
- 深入理解Mysql——鎖、事務與併發控制MySql