本文是MySQL 8.0 Dynamic Redo Log Sizing[1]這篇文章的翻譯。如有翻譯不當的地方,敬請諒解,請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝! 這篇博文將討論MySQL 8.0.30中引入的最新功能/特性:重做日誌動態調整大小(dynamic redo log s ...
本文是MySQL 8.0 Dynamic Redo Log Sizing[1]這篇文章的翻譯。如有翻譯不當的地方,敬請諒解,請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝!
這篇博文將討論MySQL 8.0.30中引入的最新功能/特性:重做日誌動態調整大小(dynamic redo log sizing)。除了InnoDB 緩衝池(buffer pool)大小之外,我們可以說合適的重做日誌大小對於MySQL性能至關重要。有許多關於如何計算合適的重做日誌大小的博客文章。其中最經典的博客文章之一來自 Baron:How to calculate a good InnoDB log file size[2](這篇博客文章是2008年發佈的,但文中計算redo log大小的公式仍然是一個有效的公式)
現在,這個功能/特性試圖解決哪個問題呢?
在MySQL中,緩衝池(buffer pool)和重做日誌大小是不經常更改的參數設置。通常,這些參數是在資料庫安裝期間設置的;之後,它們就會被遺忘,直到一些問題出現為止。問題是過去它們是靜態的,這意味著您必須重新啟動MySQL才能使參數變更生效。
MySQL在MySQL 5.7中通過動態調整緩衝池(buffer bool)大小解決了緩衝池問題。現在,MySQL 8.0.30解決了重做日誌的這個問題。調整重做日誌大小非常簡單明瞭:
mysql> SET GLOBAL innodb_redo_log_capacity = 2*1024*1024*1024;
此參數設置可將重做日誌大小調整為比當前定義的值更大或更小的值。為了實現此目的,重做日誌文件現在駐留在datadir指定的新目錄中#innodb_redo中,除非你通過變數innodb_log_group_home_dir指定了不同的目錄。這個目錄下的重做日誌文件有兩種類型:普通重做日誌文件和備用重做日誌文件。普通重做日誌文件是正在使用的重做日誌文件。備用重做日誌文件是那些等待使用的重做日誌文件。InnoDB總共維護了32個重做日誌文件,每個文件大小等於1/32 * innodb_redo_log_capacity;但是,修改innodb_redo_log_capacity參數後,重做日誌文件大小可能會暫時有所不同。
重做日誌文件使用#ib_redoN命名約定,其中N是重做日誌文件編號。備用重做日誌文件由尾碼表示_tmp。以下示例顯示#innodb_redo 目錄中的重做日誌文件,其中 18 個活動重做日誌文件和 14 個備用重做日誌文件按順序編號。
$ ls
#ib_redo31 #ib_redo33 #ib_redo35 #ib_redo37 #ib_redo39 #ib_redo41 #ib_redo43 #ib_redo45 #ib_redo47 #ib_redo49_tmp #ib_redo51_tmp #ib_redo53_tmp #ib_redo55_tmp #ib_redo57_tmp #ib_redo59_tmp #ib_redo61_tmp
#ib_redo32 #ib_redo34 #ib_redo36 #ib_redo38 #ib_redo40 #ib_redo42 #ib_redo44 #ib_redo46 #ib_redo48 #ib_redo50_tmp #ib_redo52_tmp #ib_redo54_tmp #ib_redo56_tmp #ib_redo58_tmp #ib_redo60_tmp #ib_redo62_tmp
MySQL提供了幾個狀態變數用於監視重做日誌和重做日誌容量調整操作;例如,您可以通過查詢Innodb_redo_log_resize_status以查看調整大小操作的狀態:
mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_resize_status';
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| Innodb_redo_log_resize_status | OK |
+-------------------------------+-------+
狀態變數Innodb_redo_log_capacity_resized顯示當前重做日誌的容量限制:
mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_capacity_resized';
+----------------------------------+------------+
| Variable_name | Value |
+----------------------------------+------------+
| Innodb_redo_log_capacity_resized | 3221225472 |
+----------------------------------+------------+
其他狀態變數包括:
Innodb_redo_log_checkpoint_lsn
Innodb_redo_log_current_lsn
Innodb_redo_log_flushed_to_disk_lsn
Innodb_redo_log_logic_size
Innodb_redo_log_physical_size
Innodb_redo_log_read_only
Innodb_redo_log_uuid
MySQL 8.0.30 還引入了一些與此問題相關的新錯誤消息。其中一些包括:
ER_IB_MSG_LOG_WRITER_OUT_OF_SPACE
ER_IB_MSG_LOG_WRITER_ABORTS_LOG_ARCHIVER
ER_IB_MSG_LOG_WRITER_WAITING_FOR_ARCHIVER
ER_IB_MSG_LOG_WRITER_WAIT_ON_NEW_LOG_FILE
ER_IB_MSG_LOG_WRITER_ENTERED_EXTRA_MARGIN
ER_IB_MSG_LOG_WRITER_WAIT_ON_CONSUMER
如果您想查看更多信息,可以使用此鏈接[3]。所有與重做日誌錯誤相關的消息都使用ER_IB_MSG_LOG_WRITER_ 命名約定。
估計重做日誌容量
有了這些新的狀態變數,我們可以使用以下查詢來估計重做日誌大小:
mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_current_lsn'; SELECT SLEEP(60); SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_current_lsn';
根據上一個查詢提供的輸出,我們運行以下命令:
mysql > SELECT ABS(20641693317 - 20903377487) / 1024 / 1024 AS MB_per_min;
+--------------+
| MB_per_min |
+--------------+
| 249.56147194 |
+--------------+
1 row in set (0.00 sec)
因此,在這種情況下,在重做日誌文件中寫入大約為250MB/分鐘,那麼一小時恰好是 250*60(1 小時),相當於 15GB。
已棄用的參數
為了實現這個新功能,MySQL 棄用了兩個參數:innodb_log_files_in_group和innodb_log_file_size 。
如果您嘗試在文件中設置它們my.cnf,它們將被忽略,並且錯誤日誌中將列印警告:
2022-08-07T20:23:39.898370Z 0 [Warning] [MY-013869] [InnoDB] Ignored deprecated configuration parameter innodb_log_file_size. Used innodb_redo_log_capacity instead.
2022-08-07T20:23:39.898441Z 0 [Warning] [MY-013870] [InnoDB] Ignored deprecated configuration parameter innodb_log_files_in_group. Used innodb_redo_log_capacity instead.
結論
重做日誌動態調整大小為 DBA 提供了更大的靈活性,以防萬一需要調整重做日誌大小,應用程式不能因MySQL重新啟動而停止對外服務的情況。截至撰寫本文時,還沒有與此功能相關的錯誤報告。建議之一是檢查您的備份工具是否與 MySQL 8.0.30 及其新功能相容。最後,由於一些參數已經棄用,請務必檢查現有的my.cnf配置文件。
參考資料
1: https://www.percona.com/blog/mysql-8-0-dynamic-redo-log-sizing/
[2]2: https://www.percona.com/blog/2008/11/21/how-to-calculate-a-good-innodb-log-file-size/
[3]3: https://github.com/mysql/mysql-server/blob/8.0/share/messages_to_error_log.txt