圖解MySQL | [原理解析] MySQL insert 語句的磁盤寫入之旅

做者及簡介:
黃 炎,愛可生首席技術官;
王 悅,愛可生研發團隊成員,負責數據庫管理平臺相關項目的開發和故障排查,好奇 MySQL 技術原理及各種數據庫實現方案。
本文來源:轉載自公衆號-圖解 MySQL
*愛可生開源社區出品,原創內容未經受權不得隨意使用,轉載請聯繫小編並註明來源。

一條 insert 語句在寫入磁盤的過程當中到底涉及了哪些文件?順序又是如何的?下面咱們用兩張圖和你們一塊兒解析 insert 語句的磁盤寫入之旅。數據庫

圖 1:事務提交前的日誌文件寫入

1.jpg

旅途過程:

  1. 首先 insert 進入 server 層後,會進行一些必要的檢查,檢查的過程當中並不會涉及到磁盤的寫入。
  2. 檢查沒有問題以後,便進入引擎層開始正式的提交。咱們知道 InnoDB 會將數據頁緩存至內存中的 buffer pool,因此 insert 語句到了這裏並不須要馬上將數據寫入磁盤文件中,只須要修改 buffer pool 當中對應的數據頁就能夠了。
  • buffer pool 中的數據頁刷盤並不須要在事務提交前完成,其中的交互過程咱們會在下一張圖中分解。
  1. 但僅僅寫入內存的 buffer pool 並不能保證數據的持久化,若是 MySQL 宕機重啓了,須要保證 insert 的數據不會丟失。redo log 所以而生,當 innodb_flush_log_at_trx_commit=1 時,每次事務提交都會觸發一次 redo log 刷盤。(redo log 是順序寫入,相比直接修改數據文件,redo 的磁盤寫入效率更加高效)
  2. 若是開啓了 binlog 日誌,咱們還需將事務邏輯數據寫入 binlog 文件,且爲了保證複製安全,建議使用 sync_binlog=1 ,也就是每次事務提交時,都要將 binlog 日誌的變動刷入磁盤。

綜上(在 InnoDB buffer pool 足夠大且上述的兩個參數設置爲雙一時),insert 語句成功提交時,真正發生磁盤數據寫入的,並非 MySQL 的數據文件,而是 redo log 和 binlog 文件。然而,InnoDB buffer pool 不可能無限大,redo log 也須要按期輪換,很難容下全部的數據,下面咱們就來看看 buffer pool 與磁盤數據文件的交互方式。緩存

名詞背景說明

double write 背景

InnoDB buffer pool 一頁髒頁大小爲 16 KB,若是隻寫了前 4KB 時發生宕機,那這個髒頁就發生了寫失敗,會形成數據丟失。爲了不這一問題,InnoDB 使用了 double write 機制(InnoDB 將 double write 的數據存於共享表空間中)。在寫入數據文件以前,先將髒頁寫入 double write 中,固然這裏的寫入都是須要刷盤的。有人會問 redo log 不是也能恢復數據頁嗎?爲何還須要 double write?這是由於 redo log 中記錄的是頁的偏移量,好比在頁偏移量爲 800 的地方寫入數據 xxx,而若是頁自己已經發生損壞,應用 redo log 也無濟於事。安全

insert buffer 背景

InnoDB 的數據是根據彙集索引排列的,一般業務在插入數據時是按照主鍵遞增的,因此插入彙集索引通常是順序磁盤寫入。可是不可能每張表都只有彙集索引,當存在非彙集索引時,對於非彙集索引的變動就可能不是順序的,會拖慢總體的插入性能。爲了解決這一問題,InnoDB 使用了 insert buffer 機制,將對於非彙集索引的變動先放入 insert buffer ,儘可能合併一些數據頁後再寫入實際的非彙集索引中去。性能

圖 2:事務提交後的數據文件寫入

2.jpg

旅途過程:

  1. 當 buffer pool 中的數據頁達到必定量的髒頁或 InnoDB 的 IO 壓力較小 時,都會觸發髒頁的刷盤操做。
  2. 當開啓 double write 時,InnoDB 刷髒頁時首先會複製一份刷入 double write,在這個過程當中,因爲double write的頁是連續的,對磁盤的寫入也是順序操做,性能消耗不大。
  3. 不管是否通過 double write,髒頁最終仍是須要刷入表空間的數據文件。刷入完成後才能釋放 buffer pool 當中的空間。
  4. insert buffer 也是 buffer pool 中的一部分,當 buffer pool 空間不足須要交換出部分髒頁時,有可能將 insert buffer 的數據頁換出,刷入共享表空間中的 insert buffer 數據文件中。
  5. 當 innodb_stats_persistent=ON 時,SQL 語句所涉及到的 InnoDB 統計信息也會被刷盤到 innodb_table_stats 和 innodb_index_stats 這兩張系統表中,這樣就不用每次再實時計算了。
  6. 有一些狀況下能夠不通過 double write 直接刷盤spa

    • a. 關閉 double write
    • b. 不須要 double write 保障,如 drop table 等操做

彙總兩張圖,一條 insert 語句的全部涉及到的數據在磁盤上會依次寫入 redo log,binlog,(double write,insert buffer) 共享表空間,最後在本身的用戶表空間落定爲安。日誌

相關文章
相關標籤/搜索