文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


17.6.5 重做日誌

重做日誌是一種基於磁碟的資料結構,用於在當機還原期間更正不完整交易所寫入的資料。在正常操作期間,重做日誌會編碼因 SQL 陳述式或低階 API 呼叫而導致的資料表資料變更請求。在意外關機之前未完成更新資料檔案的修改,會在初始化期間且在接受連線之前自動重播。如需重做日誌在當機還原中的作用的資訊,請參閱第 17.18.2 節,「InnoDB 還原」

重做日誌在磁碟上以重做日誌檔案呈現。寫入重做日誌檔案的資料會根據受影響的記錄進行編碼,而此資料統稱為重做。資料通過重做日誌檔案的過程由不斷增加的LSN值表示。重做日誌資料會在發生資料修改時附加,而最舊的資料會在檢查點進展時截斷。

與重做日誌相關的資訊和程序在本節的以下主題中說明

配置重做日誌容量

innodb_redo_log_capacity 系統變數控制重做日誌檔案佔用的磁碟空間量。您可以使用選項檔案在啟動時或使用 SET GLOBAL 陳述式在執行期間設定此變數;例如,以下陳述式會將重做日誌容量設定為 8GB

SET GLOBAL innodb_redo_log_capacity = 8589934592;

當在執行階段設定時,組態變更會立即發生,但新限制可能需要一些時間才能完全實施。如果重做日誌檔案佔用的空間小於指定的值,則會較不積極地將緩衝池中的髒頁刷新到表空間資料檔案,最終會增加重做日誌檔案佔用的磁碟空間。如果重做日誌檔案佔用的空間大於指定的值,則會更積極地刷新髒頁,最終會減少重做日誌檔案佔用的磁碟空間。

如果未定義 innodb_redo_log_capacity,且未定義 innodb_log_file_sizeinnodb_log_files_in_group,則會使用預設的 innodb_redo_log_capacity 值。

如果未定義 innodb_redo_log_capacity,且定義了 innodb_log_file_size 和/或 innodb_log_files_in_group,則 InnoDB 重做日誌容量的計算方式為 (innodb_log_files_in_group * innodb_log_file_size)。此計算不會修改未使用的 innodb_redo_log_capacity 設定值。

Innodb_redo_log_capacity_resized 伺服器狀態變數表示所有重做日誌檔案的總重做日誌容量。

重做日誌檔案位於資料目錄中的 #innodb_redo 目錄中,除非透過 innodb_log_group_home_dir 變數指定了不同的目錄。如果定義了 innodb_log_group_home_dir,則重做日誌檔案位於該目錄中的 #innodb_redo 目錄中。重做日誌檔案有兩種型別:一般和備用。一般重做日誌檔案是正在使用的檔案。備用重做日誌檔案是等待使用的檔案。InnoDB 嘗試維護總共 32 個重做日誌檔案,每個檔案的大小等於 1/32 * innodb_redo_log_capacity;但是,在修改 innodb_redo_log_capacity 設定後,檔案大小可能會暫時不同。

重做日誌檔案使用 #ib_redoN 的命名慣例,其中 N 是重做日誌檔案編號。備用重做日誌檔案會以 _tmp 後綴表示。以下範例顯示 #innodb_redo 目錄中的重做日誌檔案,其中有 21 個作用中的重做日誌檔案和 11 個備用重做日誌檔案,依序編號。

'#ib_redo582'  '#ib_redo590'  '#ib_redo598'      '#ib_redo606_tmp'
'#ib_redo583'  '#ib_redo591'  '#ib_redo599'      '#ib_redo607_tmp'
'#ib_redo584'  '#ib_redo592'  '#ib_redo600'      '#ib_redo608_tmp'
'#ib_redo585'  '#ib_redo593'  '#ib_redo601'      '#ib_redo609_tmp'
'#ib_redo586'  '#ib_redo594'  '#ib_redo602'      '#ib_redo610_tmp'
'#ib_redo587'  '#ib_redo595'  '#ib_redo603_tmp'  '#ib_redo611_tmp'
'#ib_redo588'  '#ib_redo596'  '#ib_redo604_tmp'  '#ib_redo612_tmp'
'#ib_redo589'  '#ib_redo597'  '#ib_redo605_tmp'  '#ib_redo613_tmp'

每個一般重做日誌檔案都與特定範圍的 LSN 值相關聯;例如,以下查詢顯示先前範例中列出的作用中重做日誌檔案的 START_LSNEND_LSN 值。

mysql> SELECT FILE_NAME, START_LSN, END_LSN FROM performance_schema.innodb_redo_log_files;
+----------------------------+--------------+--------------+
| FILE_NAME                  | START_LSN    | END_LSN      |
+----------------------------+--------------+--------------+
| ./#innodb_redo/#ib_redo582 | 117654982144 | 117658256896 |
| ./#innodb_redo/#ib_redo583 | 117658256896 | 117661531648 |
| ./#innodb_redo/#ib_redo584 | 117661531648 | 117664806400 |
| ./#innodb_redo/#ib_redo585 | 117664806400 | 117668081152 |
| ./#innodb_redo/#ib_redo586 | 117668081152 | 117671355904 |
| ./#innodb_redo/#ib_redo587 | 117671355904 | 117674630656 |
| ./#innodb_redo/#ib_redo588 | 117674630656 | 117677905408 |
| ./#innodb_redo/#ib_redo589 | 117677905408 | 117681180160 |
| ./#innodb_redo/#ib_redo590 | 117681180160 | 117684454912 |
| ./#innodb_redo/#ib_redo591 | 117684454912 | 117687729664 |
| ./#innodb_redo/#ib_redo592 | 117687729664 | 117691004416 |
| ./#innodb_redo/#ib_redo593 | 117691004416 | 117694279168 |
| ./#innodb_redo/#ib_redo594 | 117694279168 | 117697553920 |
| ./#innodb_redo/#ib_redo595 | 117697553920 | 117700828672 |
| ./#innodb_redo/#ib_redo596 | 117700828672 | 117704103424 |
| ./#innodb_redo/#ib_redo597 | 117704103424 | 117707378176 |
| ./#innodb_redo/#ib_redo598 | 117707378176 | 117710652928 |
| ./#innodb_redo/#ib_redo599 | 117710652928 | 117713927680 |
| ./#innodb_redo/#ib_redo600 | 117713927680 | 117717202432 |
| ./#innodb_redo/#ib_redo601 | 117717202432 | 117720477184 |
| ./#innodb_redo/#ib_redo602 | 117720477184 | 117723751936 |
+----------------------------+--------------+--------------+

在執行檢查點時,InnoDB 會將檢查點 LSN 儲存在包含此 LSN 的檔案標頭中。在復原期間,會檢查所有重做日誌檔案,並從最新的檢查點 LSN 開始復原。

提供了數個狀態變數,用於監控重做日誌和重做日誌容量調整大小作業;例如,您可以查詢 Innodb_redo_log_resize_status 以檢視調整大小作業的狀態。

mysql> SHOW STATUS LIKE 'Innodb_redo_log_resize_status';
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| Innodb_redo_log_resize_status | OK    |
+-------------------------------+-------+

Innodb_redo_log_capacity_resized 狀態變數會顯示目前的重做日誌容量限制。

mysql> SHOW STATUS LIKE 'Innodb_redo_log_capacity_resized';
 +----------------------------------+-----------+
| Variable_name                    | Value     |
+----------------------------------+-----------+
| Innodb_redo_log_capacity_resized | 104857600 |
+----------------------------------+-----------+

其他適用的狀態變數包括:

如需更多資訊,請參閱狀態變數說明。

您可以透過查詢 innodb_redo_log_files Performance Schema 表格來檢視有關作用中重做日誌檔案的資訊。以下查詢會從表格的所有欄位擷取資料。

SELECT FILE_ID, START_LSN, END_LSN, SIZE_IN_BYTES, IS_FULL, CONSUMER_LEVEL 
FROM performance_schema.innodb_redo_log_files;

自動重做日誌容量配置

當啟用 innodb_dedicated_server 時,InnoDB 會自動配置某些 InnoDB 參數,包括重做日誌容量。自動化配置適用於位於專用於 MySQL 的伺服器上的 MySQL 執行個體,其中 MySQL 伺服器可以使用所有可用的系統資源。如需更多資訊,請參閱第 17.8.12 節「為專用 MySQL 伺服器啟用自動配置」

重做日誌歸檔

複製重做日誌記錄的備份公用程式有時可能無法跟上備份作業進行時重做日誌的產生速度,導致由於這些記錄被覆寫而遺失重做日誌記錄。當備份作業期間有大量的 MySQL 伺服器活動,且重做日誌檔案儲存媒體的運作速度比備份儲存媒體更快時,最常發生此問題。重做日誌歸檔功能透過將重做日誌記錄循序寫入歸檔檔案(除了重做日誌檔案之外)來解決此問題。備份公用程式可以視需要從歸檔檔案複製重做日誌記錄,從而避免潛在的資料遺失。

如果伺服器上配置了重做日誌歸檔,則 MySQL Enterprise Backup(隨 MySQL Enterprise Edition 提供)會在備份 MySQL 伺服器時使用重做日誌歸檔功能。

在伺服器上啟用重做日誌歸檔需要為 innodb_redo_log_archive_dirs 系統變數設定值。該值指定為以分號分隔的標籤式重做日誌歸檔目錄清單。標籤:目錄 配對以冒號 (:) 分隔。例如:

mysql> SET GLOBAL innodb_redo_log_archive_dirs='label1:directory_path1[;label2:directory_path2;…]';

標籤 是歸檔目錄的任意識別碼。它可以是任何字元字串,但冒號 (:) 除外,冒號是不允許的。也允許使用空標籤,但在此情況下仍然需要冒號 (:)。目錄路徑 必須指定。選取用於重做日誌歸檔檔案的目錄必須在啟用重做日誌歸檔時存在,否則會傳回錯誤。路徑可以包含冒號 (':'),但不允許使用分號 (;)。

必須先配置 innodb_redo_log_archive_dirs 變數,才能啟用重做日誌歸檔。預設值為 NULL,不允許啟用重做日誌歸檔。

注意事項

您指定的歸檔目錄必須滿足以下要求。(當啟用重做日誌歸檔時,會強制執行這些要求。)

  • 目錄必須存在。重做日誌歸檔程序不會建立目錄。否則,會傳回以下錯誤:

    ERROR 3844 (HY000): Redo log archive directory 'directory_path1' does not exist or is not a directory (重做日誌歸檔目錄 'directory_path1' 不存在或不是目錄)

  • 目錄不得可供全世界存取。這是為了防止重做日誌資料暴露給系統上未經授權的使用者。否則,會傳回以下錯誤:

    ERROR 3846 (HY000): Redo log archive directory 'directory_path1' is accessible to all OS users (重做日誌歸檔目錄 'directory_path1' 可供所有 OS 使用者存取)

  • 目錄不能是由 datadirinnodb_data_home_dirinnodb_directoriesinnodb_log_group_home_dirinnodb_temp_tablespaces_dirinnodb_tmpdirinnodb_undo_directorysecure_file_priv 定義的目錄,也不能是這些目錄的父目錄或子目錄。否則,會傳回類似以下的錯誤:

    ERROR 3845 (HY000): Redo log archive directory 'directory_path1' is in, under, or over server directory 'datadir' - '/path/to/data_directory' (重做日誌歸檔目錄 'directory_path1' 位於伺服器目錄 'datadir' - '/path/to/data_directory' 內、下方或上方)

當支援重做日誌歸檔的備份公用程式啟動備份時,備份公用程式會透過叫用 innodb_redo_log_archive_start() 函數來啟用重做日誌歸檔。

如果您未使用支援重做日誌歸檔的備份公用程式,也可以手動啟用重做日誌歸檔,如下所示:

mysql> SELECT innodb_redo_log_archive_start('label', 'subdir');
+------------------------------------------+
| innodb_redo_log_archive_start('label') |
+------------------------------------------+
| 0                                        |
+------------------------------------------+

mysql> DO innodb_redo_log_archive_start('label', 'subdir');
Query OK, 0 rows affected (0.09 sec)
注意

啟用重做日誌歸檔的 MySQL 工作階段(使用 innodb_redo_log_archive_start())必須在歸檔期間保持開啟。同一個工作階段必須停用重做日誌歸檔(使用 innodb_redo_log_archive_stop())。如果在明確停用重做日誌歸檔之前終止工作階段,則伺服器會隱式停用重做日誌歸檔,並移除重做日誌歸檔檔案。

其中 標籤 是由 innodb_redo_log_archive_dirs 定義的標籤;subdir 是用於指定由 標籤 識別的目錄的子目錄以儲存歸檔檔案的可選引數;它必須是簡單的目錄名稱(不允許使用斜線 (/)、反斜線 (\) 或冒號 (:))。subdir 可以是空的、null 或可以省略。

只有具有 INNODB_REDO_LOG_ARCHIVE 權限的使用者才能透過叫用 innodb_redo_log_archive_start() 來啟用重做日誌歸檔,或使用 innodb_redo_log_archive_stop() 來停用它。執行備份公用程式的 MySQL 使用者或手動啟用和停用重做日誌歸檔的 MySQL 使用者必須具有此權限。

重做日誌歸檔檔案路徑為 由標籤識別的目錄/[子目錄/]archive.伺服器UUID.000001.log,其中 由標籤識別的目錄 是由 innodb_redo_log_archive_start()標籤 引數識別的歸檔目錄。子目錄 是用於 innodb_redo_log_archive_start() 的可選引數。

例如,重做日誌歸檔檔案的完整路徑和名稱看起來類似如下:

/directory_path/subdirectory/archive.e71a47dc-61f8-11e9-a3cb-080027154b4d.000001.log

在備份公用程式完成複製 InnoDB 資料檔案後,它會呼叫 innodb_redo_log_archive_stop() 函數來停用重做日誌歸檔。

如果您未使用支援重做日誌歸檔的備份公用程式,也可以手動停用重做日誌歸檔,如下所示:

mysql> SELECT innodb_redo_log_archive_stop();
+--------------------------------+
| innodb_redo_log_archive_stop() |
+--------------------------------+
| 0                              |
+--------------------------------+

mysql> DO innodb_redo_log_archive_stop();
Query OK, 0 rows affected (0.01 sec)

停止函式成功完成後,備份工具會從封存檔中尋找相關的重做日誌資料區段,並將其複製到備份中。

在備份工具完成複製重做日誌資料且不再需要重做日誌封存檔後,它會刪除該封存檔。

在正常情況下,刪除封存檔是備份工具的責任。然而,如果在呼叫 innodb_redo_log_archive_stop() 之前,重做日誌封存操作意外中止,MySQL 伺服器會刪除該檔案。

效能考量

由於額外的寫入活動,啟用重做日誌封存通常會產生些微的效能成本。

在 Unix 和類 Unix 作業系統上,如果沒有持續的高更新率,效能影響通常很小。在 Windows 上,假設情況相同,效能影響通常會稍微高一些。

如果有持續的高更新率,且重做日誌封存檔與重做日誌檔案位於相同的儲存媒體上,則由於複合的寫入活動,效能影響可能會更顯著。

如果有持續的高更新率,且重做日誌封存檔位於比重做日誌檔案慢的儲存媒體上,則效能會受到任意影響。

寫入重做日誌封存檔不會妨礙正常的交易日誌記錄,除非重做日誌封存檔的儲存媒體運作速度遠低於重做日誌檔案的儲存媒體,並且有大量的已持久化重做日誌區塊正在等待寫入重做日誌封存檔。在這種情況下,交易日誌記錄速率會降低到慢速儲存媒體(重做日誌封存檔所在位置)可以管理的水平。

停用重做日誌記錄

您可以使用 ALTER INSTANCE DISABLE INNODB REDO_LOG 語法來停用重做日誌記錄。此功能旨在將資料載入新的 MySQL 執行個體。停用重做日誌記錄可以避免重做日誌寫入和雙寫緩衝,從而加快資料載入速度。

警告

此功能僅適用於將資料載入新的 MySQL 執行個體。請勿在生產系統上停用重做日誌記錄。允許在停用重做日誌記錄時關閉並重新啟動伺服器,但如果在停用重做日誌記錄時發生意外的伺服器停止,可能會導致資料遺失和執行個體損毀。

如果在停用重做日誌記錄時發生意外的伺服器停止後嘗試重新啟動伺服器,將會被拒絕,並出現以下錯誤

[ERROR] [MY-013598] [InnoDB] Server was killed when Innodb Redo 
logging was disabled. Data files could be corrupt. You can try 
to restart the database with innodb_force_recovery=6

在這種情況下,請初始化新的 MySQL 執行個體並再次開始資料載入程序。

啟用和停用重做日誌記錄需要 INNODB_REDO_LOG_ENABLE 權限。

可以使用 Innodb_redo_log_enabled 狀態變數來監視重做日誌記錄狀態。

在停用重做日誌記錄時,不允許執行複製操作和重做日誌封存,反之亦然。

ALTER INSTANCE [ENABLE|DISABLE] INNODB REDO_LOG 操作需要獨佔備份中繼資料鎖定,這會阻止其他 ALTER INSTANCE 操作同時執行。其他 ALTER INSTANCE 操作必須等待鎖定釋放後才能執行。

以下程序示範如何在將資料載入新的 MySQL 執行個體時停用重做日誌記錄。

  1. 在新的 MySQL 執行個體上,將 INNODB_REDO_LOG_ENABLE 權限授予負責停用重做日誌記錄的使用者帳戶。

    mysql> GRANT INNODB_REDO_LOG_ENABLE ON *.* to 'data_load_admin';
  2. data_load_admin 使用者身分,停用重做日誌記錄

    mysql> ALTER INSTANCE DISABLE INNODB REDO_LOG;
  3. 檢查 Innodb_redo_log_enabled 狀態變數,以確保重做日誌記錄已停用。

    mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Innodb_redo_log_enabled | OFF   |
    +-------------------------+-------+
  4. 執行資料載入操作。

  5. data_load_admin 使用者身分,在資料載入操作完成後啟用重做日誌記錄

    mysql> ALTER INSTANCE ENABLE INNODB REDO_LOG;
  6. 檢查 Innodb_redo_log_enabled 狀態變數,以確保重做日誌記錄已啟用。

    mysql> SHOW GLOBAL STATUS LIKE 'Innodb_redo_log_enabled';
    +-------------------------+-------+
    | Variable_name           | Value |
    +-------------------------+-------+
    | Innodb_redo_log_enabled | ON    |
    +-------------------------+-------+