MyRocks早期隻支援排他鎖,支援SELEC… IN SHARE MODE後,MyRocks才開始引入共享鎖。
MyRocks的鎖都是記憶體鎖,是以MyRocks事務不宜持有過多的鎖,以避免占用過多的記憶體。
MyRocks通過參數rocksdb_max_row_locks來控制單個事務所持有鎖的總數。另外,rocksdb鎖系統還支援以下參數
max_num_locks:系統鎖個數總限制
expiration_time:鎖過期時間
如果鎖個數超出限制,用戶端會傳回下面的錯誤
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表都指定主鍵。
以此表結構來分析各類語句的加鎖情況。
示例 select
MVCC, 普通讀不加鎖
示例 select .. in share mode
對主鍵id=1記錄加S鎖
示例 select .. for update
對主鍵id=1記錄加X鎖
示例 insert
主鍵id=1加X鎖
唯一索引c1=1加X鎖
示例 delete by主鍵
示例 delete by唯一索引
主鍵id=2加X鎖,其他索引不加鎖
示例 delete by普通索引
主鍵id=3加X鎖,其他索引不加鎖
示例 delete by無索引
對主鍵每條加X鎖,其他索引不加鎖
實際上server層過濾不符合條件的行會釋放鎖,最終隻對主鍵id=4加X鎖
示例 delete by 主鍵不存在的行
主鍵id=100加X鎖
示例 delete by 其他索引不存在的行
沒有鎖可以加
以上例子基本可以覆寫所有加鎖的情況,再舉例幾個例子練習下
示例 select for update
主鍵id=3加X鎖, 其他索引不加鎖
示例 update更新無索引列
示例 update更新索引列
同時會對唯一索引c2=5加X鎖
對于無主鍵表的表說,RocksDB内部會有隐式主鍵,所加鎖都在隐式主鍵上
事務送出或復原時都會将事務所持有的鎖都釋放掉。
另外一種情況是,對于不滿足查詢條件的記錄,MySQL會提前釋放鎖。
MyRocks隻會對主鍵和唯一索引加鎖,普通索引不會加鎖。
隻有插入或更新了唯一索引時,才會對唯一索引加鎖,對唯一索引加鎖的目的是為了保證唯一性。
按主鍵鎖定查找不存在的行時,會對不存在的行主鍵加X鎖。
按二級索引查找時,隻會對主鍵加鎖,不會對二級鎖引加鎖。
S鎖隻應用于SELECT … IN SHARE MODE語句。
最後提供一些堆棧資訊,友善學習
走唯一索引對主鍵加鎖
送出時解鎖