Mysql和其他大多數資料庫中的事務型存盤引擎的實作一般都不是簡單的行鎖,一般基于提升并發性能考慮,他們一般都會實作多版本并發控制(MVCC),他們實作的機制都不太一樣,
這里可以將MVCC看做成是一個行鎖+讀鎖的一種合理的組合方式,(但本身是沒有進行加鎖的操作的)
MVCC的實作是通過保存某個時間點的快照(ReadView)來實作的,
————————————————————————————————————————————————————————
ReadView決議
| m_ids | 表示當前還沒提交的事務id的串列 |
| min_trx_id | 表示串列中最小的事務id |
| max_trx_id | 表示串列中最大的事務id+1(即:即將分配的事務id) |
| creator_trx_id | 表示當前事務的事務id |
ReadView判斷版本鏈中可用的判斷依據
- trx_id == creator_trx_id ——》 可以訪問的版本(代表自己建立的事務版本)
- trx_id < min_trx_id——》 可以訪問這個版本(代表已經提交過的事務版本)
- trx_id > max_trx_id ——》 不可以訪問這個版本
- min_trx_id <= trx_id <= max_trx_id ——》如果在m_ids(沒有提交的事務id)中則不可以訪問,如果沒在則事務的執行緒已經超車完成提交了事務,則可以訪問
注:trx_id是訪問的事務版本id,當是select查詢陳述句的時候id并不是為零,會有自己的一套生成規則,(聽大佬的參考:《mysql是怎樣運行的》,自己不摸魚以后過來重新補充改改)
————————————————————————————————————————————————————————
拿InnoDB引擎的MVCC來說,它是通過在每行資料的后面加上隱藏的三列來實作的,即
row_id:確認當前行唯一用的,有主鍵或者唯一索引的時候不生成,
transaction_id:事務id,就是當前行的事務版本號,
roll_pointer:回滾指標,指向undolog記錄的當前資料的上一個版本的指標,(undolog會記錄很多個版本,一個版本的指標指向上個版本,會形成一個鏈,就叫版本鏈)
每當有一個新的事務開啟的時候,就會有一個與其對應的事務版本號,系統版本號都會遞增,這里面我們拿repeatable read(可重復讀)隔離級別下的MVCC操作來舉個例子:
Insert操作:為新插入的每一行保存當前系統版本號作為當前行的版本號,
Delete操作:為洗掉的每一行保存當前系統版本號為當前行的版本號,
Update操作:為插入一行的新紀錄保存當前版本號作為當前行的版本號,
Select操作:也會生成一個對應的事務id,然后進行當前事務id的進行判斷,
然后就會根據版本鏈中的對應的版本號進行資料讀取,
MVCC只在可重復讀和讀已提交兩個隔離級別下生效,其余隔離級別下是不需要的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/299558.html
標籤:Java
上一篇:重寫和多載的區別
