首頁 > 軟體

深入理解MySQL中MVCC與BufferPool快取機制

2022-05-25 14:04:10

一、MVCC機制

  • MVCC(Multi Version Concurrency Control),MySQL(預設)RR隔離級別就是通過該機制來保證的,對一行資料的讀與寫兩個操作預設是不會通過加鎖互斥來保證隔離性的
  • 序列化隔離級別是為了保證較高的隔離性,是通過將所有操作加鎖互斥來實現的
  • MySQL在RC隔離級別和RR隔離級別下都實現了MVCC機制
  • RC每次查詢都會建立一個reade-view,而RR在建立完read-view之後,在不提交事務之前,每次查詢還是第一次建立的read-view

undo紀錄檔版本鏈與read-view機制

  • undo紀錄檔版本鏈是指一行資料被多個事務一次修改後,當每個事務修改完之後,MySQL會保留修改前的資料undo回滾紀錄檔,並且用兩個隱藏欄位trx_id和roll_pointer把只寫undo紀錄檔串聯起來形成一個歷史記錄版本鏈.
  • RR隔離級別,當事務開啟,執行任何SQL時會生成當前事務的read-view一致性檢視,該檢視在事務結束之前都不會變化(如果是RC隔離界別在每次執行查詢SQL時都會重新生成最新的read-view),這個檢視由執行查詢時所有未提交的事務id陣列(陣列裡最小的id為min_id)和已建立的最大事務id(max_id)組成,事務裡任何SQL查詢結果需要從對應版本鏈裡的最新資料開始逐條跟read-view作比對,從而得到最終的結果

版本鏈比對規則

  • 如果row的trx_id落在綠色部分(trx < min_id),表示這個版本是已提交的事務生成的,這個資料是可見的
  • 如果row的trx_id落在紅色部分(trx > max_id),表示這個版本是由將來啟動的(未開始)事務生成的,是不可見的(若row的trx_id就是當前自己的事務是可見的)
  • 如果 row 的 trx_id 落在黃色部分(min_id <= trx_id <= max_id),那就包括兩種情況
    • 若 row 的 trx_id 在檢視陣列中,表示這個版本是由還沒提交的事務生成的不可見(若 row 的 trx_id 就是當前自己的事務是可見的)
    • 若 row 的 trx_id 不在檢視陣列中,表示這個版本是已經提交了的事務生成的可見

二、BufferPool機制

InnoDB執行的BufferPool快取機制:

InnoDB的SQL執行流程:

  • 當用戶端執行一條修改的SQL,需要經過Server層,再呼叫具體的執行引擎
  • 載入資料頁,把需要修改資料所在的資料頁,快取到BufferPool
  • 修改前寫undo紀錄檔,記錄更改前資料,如果事務執行失敗,使用undo紀錄檔進行資料回滾
  • 更新BufferPool中的資料
  • 準備提交事務寫redo紀錄檔,儲存操作記錄。redo紀錄檔用來恢復已提交事務的BufferPool
  • 準備提交事務寫binlog紀錄檔,儲存操作記錄。binlog紀錄檔用來恢復磁碟資料
  • 事務提交完成,此時binlog紀錄檔寫入成功,並且在redo紀錄檔中記錄了commit標記。事務提交完成後binlog紀錄檔和redo紀錄檔資料保持一致
  • 資料持久化,IO執行緒不定期把BufferPool中的資料隨機寫入到磁碟,完成持久化

三、總結

MVCC實現機制(為什麼同一個事務第一次查詢出來之後,就算其它事務把新資料修改了,當前事務還是看到之前的資料)

  • 它內部實際有個undo紀錄檔版本鏈,然後在事務第一次查詢的時候,它會生成一個read-view一致性檢視,然後我們後面所有查詢的資料都會根據我們的那個undo紀錄檔版本鏈去跟我們當前的read-view裡面按照一定的規則逐行去比對查詢對應的資料

BufferPool機制

  • 資料庫的增刪改查都是直接操作BufferPool的,當我們執行一條修改的SQL經歷過Server層之後會呼叫具體的執行引擎,然後將相關的資料頁載入到BufferPool中,修改前寫undo紀錄檔,記錄修改前的資料為了方便事務失敗之後的回滾,然後更新BufferPool,準備提交事務寫redo紀錄檔儲存操作記錄,因為如果MySQL宕機了會從redo紀錄檔中將資料恢復到BufferPool中,然後會寫binlog紀錄檔,儲存操作記錄,因為當我們刪除資料庫跑路時,binlog是用來恢復磁碟資料的,事務提交完成後,binlog紀錄檔寫入成功,並且在redo紀錄檔記錄提交標記,此時redo紀錄檔和binlog紀錄檔資料一致,而redo紀錄檔採用順序IO寫入,這樣效率堪比記憶體操作。對於資料持久化,InnoDB會有個後臺執行緒定時去將快取刷到磁碟裡

為什麼MySQL不能直接更新磁碟上的資料而是設定了這麼一套複雜的機制來執行SQL

  • 因為來一個請求直接對磁碟檔案進行隨機讀寫,然後更新磁碟檔案裡的資料效能可能相當差.
  • 因為磁碟隨機讀寫的效能是非常差的,所以直接更新磁碟檔案時不能讓資料庫抗住高並行的
  • MySQL這套機制看起來很複雜,但它可以保證每個更新請求都是更新記憶體BufferPool,然後順序寫紀錄檔檔案,同時還能保證各種異常情況下的資料一致性
  • 更新記憶體的效能是極高的,然後順序寫磁碟上的紀錄檔檔案的效能也是非常高的,要遠高於隨機讀寫磁碟檔案,正是通過這套機制,才能讓我們的MySQL資料庫在較高設定的機器上每秒可以抗下幾千甚至上完的讀寫請求

到此這篇關於深入理解MySQL中MVCC與BufferPool快取機制的文章就介紹到這了,更多相關MVCC與BufferPool快取機制內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com