

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 InnoDB 資料表空間來改善 RDS for MySQL 的損毀復原時間
<a name="Appendix.MySQL.CommonDBATasks.Tables"></a>

MySQL 中的每個資料表都包含資料表定義、資枓和索引。MySQL 儲存引擎 InnoDB 會將資料表資料和索引儲存在*資料表空間*中。InnoDB 會建立全域共用的資料表空間，其中包含資料字典和其他相關中繼資料，而且它可以包含資料表資料和索引。InnoDB 也可以針對每個資料表和分割區建立個別的資料表空間。這些個別的資料表空間會儲存在副檔名為 .ibd 的檔案中，而且每個資料表空間的標題都包含一個專門識別它的數字。

Amazon RDS 會在 MySQL 參數群組中提供名為 `innodb_file_per_table` 的參數。此參數會控制 InnoDB 是否將新的資料表資料和索引加入至共用的資料表空間 (方法為將參數值設為 0) 或加入至個別的資料表空間 (方法為將參數值設為 1)。Amazon RDS 會將 `innodb_file_per_table` 參數的預設值設為 1，這允許您捨棄個別的 InnoDB 資料表，並回收那些資料表針對資料庫執行個體使用的儲存體。在大部分使用案例中，將 `innodb_file_per_table` 參數設為 1 是建議的設定。

當您有大量的資料表 (例如，當您使用標準 (磁性) 或一般用途 SSD 儲存體時超過 1000 個資料表，或當您使用佈建 IOPS 儲存體時超過 10,000 個資料表) 時，您應該將 `innodb_file_per_table` 參數設為 0。將此參數設為 0 時，不會建立個別資料表空間，而且這樣做可縮短資料庫損毀復原所需的時間。

MySQL 會在損毀復原週期處理每個中繼檔案。相較於有多個資料表時，處理數千個資料表檔案所需的時間，可以忽略 MySQL 在共用的資料表空間中處理中繼資訊所需的時間。因為資料表空間號碼會儲存在每個檔案的標題內，所以讀取所有資料表空間檔案的合計時間可能高達七小時。例如，標準儲存體上的一百萬個 InnoDB 資料表空間在損毀復原週期可能需要五到八小時的處理時間。在某些情況下，InnoDB 可以判斷在損毀復原週期之後是否需要額外清除，以便它將開始另一個損毀復原週期，這將延長復原時間。請記住，除了處理資料表空間資訊外，損毀復原週期也會包含轉返交易、修正中斷的頁面，以及其他操作。

因為 `innodb_file_per_table` 參數位於常數群組中，所以您可以變更參數值，方法為編輯資料庫執行個體所使用的參數群組，而不必重新啟動資料庫執行個體。例如，在將設定從 1 (建立個別資料表) 變更為 0 (使用共用的資料表空間) 之後，當現有的資料表繼續具有個別資料表空間時，新的 InnoDB 資料表將新增至共用的資料表空間。若要將 InnoDB 資料表移至共用的資料表空間，您必須使用 `ALTER TABLE` 命令。

## 將多個資料表空間遷移至共用的資料表空間
<a name="Appendix.MySQL.CommonDBATasks.MigrateMultiTbs"></a>

您可以將 InnoDB 資料表的中繼資料移至它自己的資料表空間，這將根據 `innodb_file_per_table` 參數設定，重建資料表中繼資料。首先連接到您的 MySQL 資料庫執行個體，然後發出適當的命令，如下所示。如需更多詳細資訊，請參閱 [連線至您的 MySQL 資料庫執行個體](USER_ConnectToInstance.md)。

```
ALTER TABLE table_name ENGINE = InnoDB, ALGORITHM=COPY; 
```

例如，以下查詢會針對不在共用的資料表空間中的每一個 InnoDB 資料表傳回 `ALTER TABLE` 陳述式。

**若為 MySQL 5.7 資料庫執行個體：**

```
SELECT CONCAT('ALTER TABLE `', 
REPLACE(LEFT(NAME , INSTR((NAME), '/') - 1), '`', '``'), '`.`', 
REPLACE(SUBSTR(NAME FROM INSTR(NAME, '/') + 1), '`', '``'), '` ENGINE=InnoDB, ALGORITHM=COPY;') AS Query 
FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES 
WHERE SPACE <> 0 AND LEFT(NAME, INSTR((NAME), '/') - 1) NOT IN ('mysql','');
```

**適用於 MySQL 8.4 和 8.0 資料庫執行個體：**

```
SELECT CONCAT('ALTER TABLE `', 
REPLACE(LEFT(NAME , INSTR((NAME), '/') - 1), '`', '``'), '`.`', 
REPLACE(SUBSTR(NAME FROM INSTR(NAME, '/') + 1), '`', '``'), '` ENGINE=InnoDB, ALGORITHM=COPY;') AS Query 
FROM INFORMATION_SCHEMA.INNODB_TABLES 
WHERE SPACE <> 0 AND LEFT(NAME, INSTR((NAME), '/') - 1) NOT IN ('mysql','');
```

重建 MySQL 資料表將資料表的中繼資料移至共用的資料表空間，暫時需要額外的儲存空間來重建資料表，所以資料庫執行個體必須具有可用的儲存空間。重建期間，會鎖定資料表，而且查詢無法存取它。對於不經常存取的小型表格或表格，可能不需要擔心此問題。對於在大量並行環境中經常存取的大型表格或表格，您可以在僅供讀取複本上重建資料表。

您可以建立僅供讀取複本，並將資料表中繼資料遷移至僅供讀取複本上共用的資料表空間。當 ALTER TABLE 陳述式封鎖僅供讀取複本上的存取權時，來源資料庫執行個體不會受到影響。在資料表重建過程中，當僅供讀取複本延遲時，來源資料庫執行個體將繼續產生其二進位記錄。由於重建需要額外的儲存空間，重播日誌檔案可能因此變大，所以您應該建立其配置的儲存體大於來源資料庫執行個體的僅供讀取複本。

若要建立僅供讀取複本並重建 InnoDB 資料表，以使用共用的資料表空間，請採取以下步驟：

1. 確保已在來源資料庫執行個體上啟用備份保留，以便啟用二進位記錄。

1. 使用 AWS 管理主控台 或 AWS CLI 為來源資料庫執行個體建立僅供讀取複本。因為建立僅供讀取複本涉及許多與損毀復原相同的程序，所以如果有大量 InnoDB 資料表空間，則建立程序可能需要一些時間。在僅供讀取複本上配置更多的儲存空間，超過目前在來源資料庫執行個體上使用的儲存空間。

1. 建立僅供讀取複本後，請使用參數設定 `read_only = 0` 和 `innodb_file_per_table = 0` 建立參數群組。接著請將參數群組與僅供讀取複本產生關聯。

1. 針對您要在複本上遷移的所有資料表，發出下列 SQL 陳述式：

   ```
   ALTER TABLE name ENGINE = InnoDB
   ```

1. 在僅供讀取複本上完成了所有 `ALTER TABLE` 陳述式時，請驗證僅供讀取複本是否連線至來源資料庫執行個體，以及這兩個執行個體是否同步。

1. 使用主控台或 CLI 將僅供讀取複本升級為執行個體。確定用於新獨立資料庫執行個體的參數群組已將 `innodb_file_per_table` 參數設為 0。變更新獨立資料庫執行個體的名稱，並將任何應用程式指向新的獨立資料庫執行個體。