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...