Mysql

在 MySQL 中,數據究竟是如何從查詢流向磁碟的?

  • February 7, 2018

我想弄清楚從觸發查詢到進入磁碟的數據究竟是如何流動的。(我有一個粗略的想法,它會去緩衝區,然後重做日誌,然後是磁碟文件)但是那麼使用 bin_log_cache 怎麼樣。

我已經用Google搜尋了這個,但沒有找到關於這個主題的太多內容。我希望在這個社區的人們之間有一些解釋。

一個“peter zaitsev”文件系統緩衝雙寫的Google給出了幾個很好的參考(Peter Zaitsev 為 Percona 工作,他們是MySQL 世界的大熱門。

其中,我選擇了 4 個特別感興趣的 [ 1 , 2 , 3 , 4 ]。

在第一個參考文獻中,Zaitsev 給出了可能發生部分頁面寫入的各種原因的詳細介紹(標題為“現在讓我們談談部分頁面寫入”的部分)。

Zaitsev 然後繼續討論雙重寫入如何工作的部分,但我認為在參考文獻 2 中可以找到更好的解釋 - 特別是這一點:

如果數據文件中發生部分頁面寫入,如果數據文件中頁面的校驗和與雙寫緩衝區中頁面的校驗和不同,InnoDB / XtraDB 將檢查恢復,從而知道頁面是否損壞或不是。如果它被損壞,恢復過程將使用儲存在雙寫緩衝區中的頁面來恢復正確的數據。

如果在雙寫緩衝區中發生部分寫入,則原始頁面不會被觸及,並且可以與重做日誌一起使用來恢復數據。

基本上,此行為由名為innodb_flush_log_at_trx_commit的系統參數控制。這部分內容太大,無法在此處完整引用,我將僅引用有關預設值的部分內容:(我強烈建議您完整閱讀它以獲得良好的概述)。

◾ 完全符合 ACID 要求預設值 1。使用此值,InnoDB 日誌緩衝區的內容會在每次事務送出時寫入日誌文件,並將日誌文件刷新到磁碟。

但是,手冊的這一部分還說:

控制送出操作的嚴格 ACID 合規性與重新排列和批量完成送出相關的 I/O 操作時可能實現的更高性能之間的平衡。您可以通過更改預設值來獲得更好的性能,但是您可能會在崩潰中失去多達一秒鐘的事務。

用簡單的英語來說,這意味著“你得到你所支付的”——即在數據完整性和性能之間取得平衡。然而,儘管搜尋了高低,但在細節方面我找不到更多的東西——除非你想翻遍程式碼(恐怕高於我的工資等級:-))。

您可以關閉參數innodb_doublewrite,然後這會導致另一個系統參數innodb_flush_method - 這再次與性能與數據完整性有關。我的參考文獻 3 和 4 對此進行了詳細介紹 - 基本上,這兩個參考文獻中的爭論是關於如果您有事務文件系統,關閉雙寫是否是個好主意。

共識似乎是,如果您使用 ZFS(和其他,可能是深奧的文件系統/設備),您可以安全地關閉雙寫 - 假設 RAID 具有電池供電的磁碟記憶體。參考文獻 4 恕我直言,關於 ext4 是否安全的爭論仍然存在——也請參見此處

下圖很好地概述了MySQL 的 InnoDB 架構

在此處輸入圖像描述

嚴格查看二進制日誌,有一個可以遵循的流程

請注意 MySQL 文件中關於binlog_cache_size的說明:

在事務期間保存二進制日誌更改的記憶體大小。如果伺服器支持任何事務儲存引擎並且伺服器啟用了二進制日誌(–log-bin 選項),則為每個客戶端分配一個二進制日誌記憶體。如果您經常使用大型事務,則可以增加此記憶體大小以獲得更好的性能。Binlog_cache_use 和 Binlog_cache_disk_use 狀態變數可用於調整此變數的大小。請參閱第 5.4.4 節,“二進制日誌”。

由於此設置會影響事務的使用,因此在事務的生命週期中存在寫入二進制日誌的時間點。你的問題真的是**“二進制日誌什麼時候在 InnoDB Plumbing 中發揮作用?”**

由於Verace 已經展示了 InnoDB 的圖形表示,您可以看到沒有提及二進制日誌。MySQL 文件實際上提到了二進制日誌何時在事務中互動。

請注意The Binary LogMySQL 文件中的內容:

二進制日誌記錄在語句或事務完成後但在任何鎖被釋放或任何送出完成之前立即完成。這可確保日誌按送出順序記錄。

另一段說如下:

在未送出的事務中,所有更改事務表(如 InnoDB 表)的更新(UPDATE、DELETE 或 INSERT)都會被記憶體,直到伺服器接收到 COMMIT 語句。此時,mysqld 在執行 COMMIT 之前將整個事務寫入二進制日誌。

另一段關於二進制日誌的緩衝區記憶體如下:

當處理事務的執行緒啟動時,它會為緩衝區語句分配一個 binlog_cache_size 的緩衝區。如果語句大於此值,則執行緒會打開一個臨時文件來儲存事務。執行緒結束時刪除臨時文件。

概括

  • 如果流入二進制日誌記憶體的流量過多,則二進制日誌記憶體會載入語句/事務或分頁到磁碟。

  • 如果 binlog 文件事先沒有接收到一個或多個語句/事務,則任何 COMMIT 都不會到達磁碟(重做日誌、雙寫緩衝區和 InnoDB Plumbing 的其餘部分)

  • 您可能可以通過更改兩件事來調整這種互動

引用自:https://dba.stackexchange.com/questions/142224