MySql - 對update是怎麼處理的

咱們select的時候,會把數據對應的數據頁加載到緩衝池Buffer Pool,那修改的時候,其實就是修改緩衝池Buffer Pool裏的緩存頁數據,而不是直接修改磁盤的數據,這樣性能就會有比較大的提高。可是這裏會有幾個問題:數據庫

  1. 事務怎麼回滾?
  2. 存在緩存裏機器宕機了怎麼辦?緩存

    undo日誌文件

    在修改緩存頁數據以前,會先把數據寫入undo日誌文件,用來解決事務回滾。
    若是是INSERT操做,那undo日誌文件就會記錄主鍵,回滾的時候經過主鍵刪除。
    若是是UPDATE操做,那undo日誌文件就會記錄修改以前的數據,回滾的時候就會用以前的數據進行恢復。
    若是是DELETE操做,那undo日誌文件就會記錄刪除以前的數據,回滾的時候就會用以前的數據進行恢復。
    image.png服務器

    redo日誌文件

    在Buffer Pool修改數據後,接下來就是把變化的值寫入到redo日誌文件。
    若是此時已經寫入redo日誌文件,事務已經提交了,可是數據還沒寫入磁盤,MySql服務器宕機了,Buffer Pool裏修改的數據並不會修改到磁盤裏。
    當MySql重啓的時候,他會讀取redo日誌文件,把變化的值從新寫入Buffer Pool,對於客戶端來講,他讀取的時候,就是讀取Buffer Pool的值,因此客戶端讀取到的數據就是新數據。
    對於寫入redo和undo不同的是,他有一個redo緩存,首先把值寫入redo緩存而後再寫入redo日誌文件。因此他這裏會有幾種策略:性能

  3. 數據寫入緩存,事務提交。
  4. 數據寫入磁盤文件,事務提交。
  5. 寫入緩存後事務提交,一秒後寫入磁盤文件。
    從數據的可靠性來說,咱們通常選擇第二種,等寫入磁盤才提交事務。
    image.png
    爲何要寫redo而不是直接寫數據庫文件呢?
    由於寫入數據庫文件是隨機寫,寫入redo是順序寫,這邊就有很大的性能差別。spa

    binlog日誌文件

    實際上在redo寫入後,並不會直接提交事務,而是會寫入binlog歸檔日誌,然後纔會提交事務。
    與redo相似,他也提供了兩種策略:線程

  6. 寫入oscache後提交事務。
  7. 寫入磁盤後提交事務。
    從數據的可靠性來說,咱們通常選擇第二種,等寫入磁盤才提交事務。
    image.png
    寫入binlog後,他會對redo文件進行commit操做。
    好比咱們修改了10條數據,而後寫入binlog是8條,那咱們實際提交成功的事務是多少呢?要怎麼判斷呢?
    此時就須要commit來判斷了,當寫入binlog寫入後並進行commit後,才證實這條數據是成功的事務。若是沒有進行commit操做,那麼有多是寫入redo文件可是沒有寫入binlog的時候宕機了,或者已經寫入binlog可是沒有commit的時候宕機了,那這樣的事務其實就是沒有成功的。日誌

    flush鏈表

    在上面的流程中,咱們看到寫入undo日誌文件、redo日誌文件、binlog歸檔日誌,就是沒有看到怎麼寫入磁盤的。
    在MySql中,他會有一個線程,按期的把緩存頁的內容刷入到磁盤。
    那這裏又有一個問題,咱們知道Buffer Pool有不少緩存頁,那這個線程怎麼知道應該刷入哪一個緩存頁到磁盤呢?
    跟以前的free鏈表、LRU鏈表同樣,MySql也提供了一個鏈表,flush鏈表,當緩存頁的內容有修改的時候,描述數據就會加入到flush鏈表。
    因此這個線程每次從flush鏈表找到對應的緩存頁,把數據刷到磁盤,而後再把他從flush鏈表移走。
    image.png事務

相關文章
相關標籤/搜索