MyRocks事務鎖分析

2021-09-20 17:18:57 字數 4502 閱讀 3829

myrocks中rocksdb作為基於快照的事務引擎,其在事務支援上有別於innodb,有其自身的特點。在早期的月報[[myrocks之事務處理]]( 中,我們對鎖的實現有過簡單的分析,本文會以一些例子來介紹myrocks是如果來加鎖解鎖的。

myrocks早期只支援排他鎖,支援selec... in share mode後,myrocks才開始引入共享鎖。

enum 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 * from t1;
mvcc, 普通讀不加鎖

select * from t1 where id=1 in share mode;
對主鍵id=1記錄加s鎖

select * from t1 where id=1 for update;
對主鍵id=1記錄加x鎖

begin;

insert into t1 values(1,1,1,1);

rollback;

主鍵id=1加x鎖

唯一索引c1=1加x鎖

begin;

delete from t1 where id=1;

rollback;

主鍵id=1加x鎖

begin;

delete from t1 where c1=2;

rollback;

主鍵id=2加x鎖,其他索引不加鎖

begin;

delete from t1 where c2=3;

rollback;

主鍵id=3加x鎖,其他索引不加鎖

begin;

delete from t1 where c3=4;

rollback;

對主鍵每條加x鎖,其他索引不加鎖

實際上server層過濾不符合條件的行會釋放鎖,最終只對主鍵id=4加x鎖

begin;

delete from t1 where id=100;

rollback;

主鍵id=100加x鎖

begin;

delete from t1 where c1=100;

rollback;

沒有鎖可以加

以上例子基本可以覆蓋所有加鎖的情況,再舉例幾個例子練習下

begin;

select * from t1 where c2=3 for update;

rollback;

主鍵id=3加x鎖, 其他索引不加鎖

begin;

update t1 set c3=5 where c3=4;

rollback;

對主鍵每條加x鎖,其他索引不加鎖

實際上server層過濾不符合條件的行會釋放鎖,最終只對主鍵id=4加x鎖

begin;

update t1 set c2=5 where c3=4;

rollback;

對主鍵每條加x鎖,其他索引不加鎖

實際上server層過濾不符合條件的行會釋放鎖,最終只對主鍵id=4加x鎖

同時會對唯一索引c2=5加x鎖

對於無主鍵表的表說,rocksdb內部會有隱式主鍵,所加鎖都在隱式主鍵上

事務提交或回滾時都會將事務所持有的鎖都釋放掉。

另外一種情況是,對於不滿足查詢條件的記錄,mysql會提前釋放鎖。

最後提供一些堆疊資訊,方便學習

#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

MyRocks寫入分析

title mysql myrocks myrocks寫入分析 myrocks的寫入流程可以簡單的分為以下幾步來完成 將解析後的記錄 ktypevalue ktypedeletion 寫入到writebatch中 將wal日誌寫入log檔案 將writebatch中的內容寫到memtable中,事務...

myrocks記錄格式分析

title mysql myrocks myrocks記錄格式分析 rocksdb作為kv儲存引擎,那麼myrocks記錄最終會以kv的形式儲存在rocksdb中。mysql中的表一般由若干索引組成,在innodb儲存引擎中,每個索引對應一顆b樹,而在rocksdb儲存引擎中,索引對應於rocksd...

myrocks之事務處理

mysql目前支援的事務引擎有innodb,tokudb.rocksdb加入mysql陣營後,mysql支援的事務引擎增長至3個。myrocks目前支援的事務隔離級別有read committed和repeatable read.同innodb一樣,myrocks也支援mvcc機制。可以說,myro...