

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

# 將 RDS Custom for SQL Server 執行個體還原至某個時間點
<a name="custom-backup.pitr-sqs"></a>

您可以將資料庫執行個體還原至特定時間點 (PITR)，建立新的資料庫執行個體。若要支援 PITR，您的資料庫執行個體必須啟用備份保留。

RDS Custom for SQL Server 資料庫執行個體的最晚可還原時間取決於許多因素，但通常是目前時間的 5 分鐘內。若要查看資料庫執行個體的最新可還原時間，請使用AWS CLI[describe-db-instances](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-instances.html) 命令，並查看資料庫執行個體`LatestRestorableTime`欄位中傳回的值。若要在 Amazon RDS 主控台中查看每個資料庫執行個體的最新可還原時間，請選擇**自動備份**。

您可以還原至備份保留期間內的任何時間點。若要查看每個資料庫執行個體的最早可還原時間，請在 Amazon RDS 主控台中選擇**自動備份**。

如需 PITR 的一般資訊，請參閱 [將 Amazon RDS 的資料庫執行個體還原至指定時間](USER_PIT.md)。

**Topics**
+ [

## RDS Custom for SQL Server 的 PITR 考量
](#custom-backup.pitr.sqlserver)
+ [

## 每個執行個體類別類型符合 PITR 資格的資料庫數目
](#custom-backup.pitr.sqlserver.eligiblecountperinstance)
+ [

## 使資料庫不符合 PITR 的資格
](#custom-backup.pitr.sqlserver.ineligible)
+ [

## Amazon S3 中的交易日誌
](#custom-backup.pitr.sqlserver.tlogs)
+ [

## 使用 AWS 管理主控台、 AWS CLI或 RDS API 還原 PITR。
](#custom-backup.pitr-sqs-concli)

## RDS Custom for SQL Server 的 PITR 考量
<a name="custom-backup.pitr.sqlserver"></a>

在 RDS Custom for SQL Server 中，PITR 與 Amazon RDS 中的 PITR 有以下的重要不同：
+ PITR 只會還原資料庫執行個體中的資料庫。它不會還原作業系統或 C: 磁碟機上的檔案。
+ 對於 RDS Custom for SQL Server 資料庫執行個體，資料庫會自動備份，而且只有在下列條件下符合 PITR 的資格：
  + 資料庫在線上。
  + 其復原模型設定為 `FULL`。
  + 可寫入。
  + 在 D: 磁碟機上有實體檔案。
  + 並未列在 `rds_pitr_blocked_databases` 資料表中。如需詳細資訊，請參閱[使資料庫不符合 PITR 的資格](#custom-backup.pitr.sqlserver.ineligible)。
+ 符合 PITR 資格的資料庫是由其資料庫 ID 的順序決定。RDS Custom for SQL Server 最多允許每個資料庫執行個體有 5,000 個資料庫。但是 RDS Custom for SQL Server 資料庫執行個體的 PITR 操作還原的資料庫數上限取決於執行個體類別類型。如需詳細資訊，請參閱[每個執行個體類別類型符合 PITR 資格的資料庫數目](#custom-backup.pitr.sqlserver.eligiblecountperinstance)。

  其他不屬於 PITR 一部分的資料庫可以從資料庫快照還原，包括用於 PITR 的自動快照備份。
+ 新增資料庫、重新命名資料庫或還原符合 PITR 資格的資料庫，會啟動資料庫執行個體的快照。
+ 當資料庫執行個體經過擴展運算操作時，符合 PITR 資格的資料庫數目上限會變更，取決於目標執行個體類別類型。如果執行個體向上擴展，允許執行個體上的更多資料庫符合 PITR 的資格，則會擷取新的快照。
+ 還原的資料庫名稱與來源資料庫執行個體中的名稱相同。您無法指定不同的名稱。
+ `AWSRDSCustomSQLServerIamRolePolicy` 需要存取其他 AWS服務。如需詳細資訊，請參閱[將存取政策新增至 AWSRDSCustomSQLServerInstanceRole](custom-setup-sqlserver.md#custom-setup-sqlserver.iam.add-policy)。
+ 不支援 RDS Custom for SQL Server 的時區變更。如果您變更作業系統或資料庫執行個體時區，PITR (和其他自動化) 無法運作。

## 每個執行個體類別類型符合 PITR 資格的資料庫數目
<a name="custom-backup.pitr.sqlserver.eligiblecountperinstance"></a>

下表顯示根據執行個體類別類型符合 PITR 資格的資料庫數目上限。


| 執行個體類別類型 | PITR 合格資料庫的數目上限 | 
| --- | --- | 
| db.\$1.large | 100 | 
| db.\$1.xlarge 到 db.\$1.2xlarge | 150 | 
| db.\$1.4xlarge 到 db.\$1.8xlarge | 300 | 
| db.\$1.12xlarge 到 db.\$1.16xlarge | 600 | 
| db.\$1.24xlarge、db.\$132xlarge | 1000 | 

`*` *表示不同的執行個體類別類型。*

資料庫執行個體上符合 PITR 資格的資料庫數目上限取決於執行個體類別類型。在 RDS Custom for SQL Server 支援的執行個體類別類型上，數字範圍從最小 100 到最大 1000。SQL 伺服器系統資料庫 `(master, model, msdb, tempdb)` 不包含在此限制中。當資料庫執行個體向上擴展或縮減時，RDS Custom 會根據目標執行個體類別類型，自動更新符合 PITR 資格的資料庫數目。RDS Custom for SQL Server 會在資料庫執行個體上符合 PITR 資格的資料庫數目上限變更時傳送 `RDS-EVENT-0352`。如需詳細資訊，請參閱[自訂引擎版本事件](USER_Events.Messages.md#USER_Events.Messages.CEV)。

**注意**  
PITR 對超過 100 個資料庫的支援僅適用於 2023 年 8 月 26 日之後建立的資料庫執行個體。對於 2023 年 8 月 26 日之前建立的執行個體，無論執行個體類別為何，符合 PITR 資格的資料庫數目上限為 100。若要在 2023 年 8 月 26 日之前建立的資料庫執行個體上啟用超過 100 個資料庫的 PITR 支援，您可以執行下列動作：  
將資料庫引擎版本升級至 15.00.4322.2.v1 或更新版本

在 PITR 操作期間，RDS Custom 會在還原時間還原來源資料庫執行個體上屬於 PITR 一部分的所有資料庫。一旦目標資料庫執行個體完成還原操作，如果啟用備份保留，資料庫執行個體將根據目標資料庫執行個體上符合 PITR 資格的資料庫數目上限開始備份。

例如，如果您的資料庫執行個體在具有 200 個資料庫的 `db.*.xlarge` 上執行：

1. RDS Custom for SQL Server 會為 PITR 備份選擇依資料庫 ID 排序的前 150 個資料庫。

1. 您可以修改執行個體以向上擴展至 db.\$1.4xlarge。

1. 擴展運算操作完成後，RDS Custom for SQL Server 會為 PITR 備份選擇依資料庫 ID 排序的前 300 個資料庫。滿足 PITR 要求條件的 200 個資料庫現在都符合 PITR 的資格。

1. 您現在修改執行個體以縮減至 db.\$1.xlarge。

1. 擴展運算操作完成後，RDS Custom for SQL Server 會為 PITR 備份再次選取依資料庫 ID 排序的前 150 個資料庫。

## 使資料庫不符合 PITR 的資格
<a name="custom-backup.pitr.sqlserver.ineligible"></a>

您可以選擇從 PITR 排除個別資料庫。若要做到這一點，請將它們的 `database_id` 值放到 `rds_pitr_blocked_databases` 資料表。使用下列 SQL 指令碼以建立資料表。

**若要建立 rds\$1pitr\$1blocked\$1databases 資料表**
+ 執行以下 SQL 指令碼。

  ```
  create table msdb..rds_pitr_blocked_databases
  (
  database_id INT NOT NULL,
  database_name SYSNAME NOT NULL,
  db_entry_updated_date datetime NOT NULL DEFAULT GETDATE(),
  db_entry_updated_by SYSNAME NOT NULL DEFAULT CURRENT_USER,
  PRIMARY KEY (database_id)
  );
  ```

如需符合資格和不符合資格資料庫的清單，請參閱 Amazon S3 儲存貯體 `do-not-delete-rds-custom-$ACCOUNT_ID-$REGION-unique_identifier` 的 `RDSCustomForSQLServer/Instances/DB_instance_resource_ID/TransactionLogMetadata` 目錄中的 `RI.End` 檔案。如需 `RI.End` 詳細資訊，請參閱 [Amazon S3 中的交易日誌](#custom-backup.pitr.sqlserver.tlogs)。

您也可以使用下列 SQL 指令碼來判斷 PITR 的合格資料庫清單。將 `@limit` 變數設定為符合執行個體類別 PITR 資格的資料庫數目上限。如需詳細資訊，請參閱[每個執行個體類別類型符合 PITR 資格的資料庫數目](#custom-backup.pitr.sqlserver.eligiblecountperinstance)。

**判斷資料庫執行個體類別上 PITR 的合格資料庫清單**
+ 執行以下 SQL 指令碼。

  ```
  DECLARE @Limit INT;
  SET @Limit = (insert-database-instance-limit-here);
  
  USE msdb;
  IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND  TABLE_NAME = 'rds_pitr_blocked_databases'))
      WITH TABLE0 AS (
          SELECT hdrs.database_id as DatabaseId, sdb.name as DatabaseName, 'ALWAYS_ON_NOT_WRITABLE_REPLICA' as Reason, NULL as DatabaseNameOnPitrTable
          FROM sys.dm_hadr_database_replica_states hdrs
          INNER JOIN sys.databases sdb ON sdb.database_id = hdrs.database_id
          WHERE (hdrs.is_local = 1 AND hdrs.is_primary_replica = 0) 
          OR (sys.fn_hadr_is_primary_replica (sdb.name) = 1 AND DATABASEPROPERTYEX (sdb.name, 'Updateability') = 'READ_ONLY')
      ),
      TABLE1 as (
              SELECT dbs.database_id as DatabaseId, sysdbs.name as DatabaseName, 'OPTOUT' as Reason,
              CASE WHEN dbs.database_name = sysdbs.name THEN NULL ELSE dbs.database_name END AS DatabaseNameOnPitrTable
              FROM msdb.dbo.rds_pitr_blocked_databases dbs
              INNER JOIN sys.databases sysdbs ON dbs.database_id = sysdbs.database_id
              WHERE sysdbs.database_id > 4
              ),
      TABLE2 as (
              SELECT
              db.name AS DatabaseName,
              db.create_date AS CreateDate,
              db.state_desc AS DatabaseState,
              db.database_id AS DatabaseId,
              rs.database_guid AS DatabaseGuid,
              rs.last_log_backup_lsn AS LastLogBackupLSN,
              rs.recovery_fork_guid RecoveryForkGuid,
              rs.first_recovery_fork_guid AS FirstRecoveryForkGuid,
              db.recovery_model_desc AS RecoveryModel,
              db.is_auto_close_on AS IsAutoClose,
              db.is_read_only as IsReadOnly,
              NEWID() as FileName,
              CASE WHEN(db.state_desc = 'ONLINE'
                      AND db.recovery_model_desc != 'SIMPLE' 
                      AND((db.is_auto_close_on = 0 and db.collation_name IS NOT NULL) OR db.is_auto_close_on = 1)) 
                      AND db.is_read_only != 1
                      AND db.user_access = 0
                      AND db.source_database_id IS NULL
                      AND db.is_in_standby != 1
                      THEN 1 ELSE 0 END AS IsPartOfSnapshot,
              CASE WHEN db.source_database_id IS NULL THEN 0 ELSE 1 END AS IsDatabaseSnapshot
              FROM sys.databases db
              INNER JOIN sys.database_recovery_status rs
              ON db.database_id = rs.database_id
              WHERE DB_NAME(db.database_id) NOT IN('tempdb') AND
              db.database_id NOT IN (SELECT DISTINCT DatabaseId FROM TABLE1) AND
              db.database_id NOT IN (SELECT DISTINCT DatabaseId FROM TABLE0)
          ),
          TABLE3 as(
              Select @Limit+count(DatabaseName) as TotalNumberOfDatabases from TABLE2 where TABLE2.IsPartOfSnapshot=1 and DatabaseName in ('master','model','msdb')
          )
          SELECT TOP(SELECT TotalNumberOfDatabases from TABLE3)  DatabaseName,CreateDate,DatabaseState,DatabaseId from TABLE2 where TABLE2.IsPartOfSnapshot=1
          ORDER BY TABLE2.DatabaseID ASC
  ELSE
      WITH TABLE0 AS (
          SELECT hdrs.database_id as DatabaseId, sdb.name as DatabaseName, 'ALWAYS_ON_NOT_WRITABLE_REPLICA' as Reason, NULL as DatabaseNameOnPitrTable
          FROM sys.dm_hadr_database_replica_states hdrs
          INNER JOIN sys.databases sdb ON sdb.database_id = hdrs.database_id
          WHERE (hdrs.is_local = 1 AND hdrs.is_primary_replica = 0) 
          OR (sys.fn_hadr_is_primary_replica (sdb.name) = 1 AND DATABASEPROPERTYEX (sdb.name, 'Updateability') = 'READ_ONLY')
      ),
      TABLE1 as (
              SELECT
              db.name AS DatabaseName,
              db.create_date AS CreateDate,
              db.state_desc AS DatabaseState,
              db.database_id AS DatabaseId,
              rs.database_guid AS DatabaseGuid,
              rs.last_log_backup_lsn AS LastLogBackupLSN,
              rs.recovery_fork_guid RecoveryForkGuid,
              rs.first_recovery_fork_guid AS FirstRecoveryForkGuid,
              db.recovery_model_desc AS RecoveryModel,
              db.is_auto_close_on AS IsAutoClose,
              db.is_read_only as IsReadOnly,
              NEWID() as FileName,
              CASE WHEN(db.state_desc = 'ONLINE'
                      AND db.recovery_model_desc != 'SIMPLE' 
                      AND((db.is_auto_close_on = 0 and db.collation_name IS NOT NULL) OR db.is_auto_close_on = 1)) 
                      AND db.is_read_only != 1
                      AND db.user_access = 0
                      AND db.source_database_id IS NULL
                      AND db.is_in_standby != 1
                      THEN 1 ELSE 0 END AS IsPartOfSnapshot,
              CASE WHEN db.source_database_id IS NULL THEN 0 ELSE 1 END AS IsDatabaseSnapshot
              FROM sys.databases db
              INNER JOIN sys.database_recovery_status rs
              ON db.database_id = rs.database_id
              WHERE DB_NAME(db.database_id) NOT IN('tempdb') AND
              db.database_id NOT IN (SELECT DISTINCT DatabaseId FROM TABLE0)
          ),
          TABLE2 as(
              SELECT @Limit+count(DatabaseName) as TotalNumberOfDatabases from TABLE1 where TABLE1.IsPartOfSnapshot=1 and DatabaseName in ('master','model','msdb')
          )
          select top(select TotalNumberOfDatabases from TABLE2)  DatabaseName,CreateDate,DatabaseState,DatabaseId from TABLE1 where TABLE1.IsPartOfSnapshot=1
          ORDER BY TABLE1.DatabaseID ASC
  ```

**注意**  
僅有符號連結的資料庫也會從符合 PITR 操作資格的資料庫排除。上述查詢不會根據此準則進行篩選。

## Amazon S3 中的交易日誌
<a name="custom-backup.pitr.sqlserver.tlogs"></a>

備份保留期決定是否會自動擷取 RDS Custom for SQL Server 資料庫執行個體的交易日誌並上傳到 Amazon S3。非零值表示會建立自動備份，而且 RDS Custom 代理程式每 5 分鐘會將交易日誌上傳到 S3。

S3 上的交易日誌檔會使用您在建立資料庫執行個體時提供的 AWS KMS key 進行靜態加密。如需詳細資訊，請參閱《Amazon Simple Storage Service 使用者指南》**中的[使用伺服器端加密保護資料](https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html)。

每個資料庫的交易日誌會上傳至名稱為 `do-not-delete-rds-custom-$ACCOUNT_ID-$REGION-unique_identifier` 的 S3 儲存貯體。S3 儲存貯體中的 `RDSCustomForSQLServer/Instances/DB_instance_resource_ID` 目錄包含兩個子目錄：
+ `TransactionLogs` – 包含每個資料庫的交易日誌及其各自的中繼資料。

  交易日誌檔名稱遵循 `yyyyMMddHHmm.database_id.timestamp` 模式，例如：

  ```
  202110202230.11.1634769287
  ```

  具有尾碼 `_metadata` 的相同檔案名稱包含交易日誌的相關資訊，例如日誌序號、資料庫名稱和 `RdsChunkCount`。`RdsChunkCount` 會決定多少實體檔案表示單一交易日誌檔。您可能會看到具有尾碼 `_0001`、`_0002` 等等的檔案，這表示交易日誌檔的實際區塊。如果您想要使用區塊的交易日誌檔，請務必在下載區塊之後合併。

  請考量具有下列檔案的案例：
  + `202110202230.11.1634769287`
  + ` 202110202230.11.1634769287_0001`
  + ` 202110202230.11.1634769287_0002 `
  + ` 202110202230.11.1634769287_metadata`

  `RdsChunkCount` 為 `3`。合併檔案的順序如下：`202110202230.11.1634769287`、` 202110202230.11.1634769287_0001`、`202110202230.11.1634769287_0002`。
+ `TransactionLogMetadata` – 包含交易日誌擷取之每個反覆項目的相關中繼資料資訊。

  `RI.End` 檔案包含其交易日誌已擷取之所有資料庫的資訊，以及已存在但是其交易日誌未擷取之所有資料庫的資訊。`RI.End` 檔案名稱遵循 `yyyyMMddHHmm.RI.End.timestamp` 模式，例如：

  ```
  202110202230.RI.End.1634769281
  ```

## 使用 AWS 管理主控台、 AWS CLI或 RDS API 還原 PITR。
<a name="custom-backup.pitr-sqs-concli"></a>

您可以使用 AWS CLI、 或 RDS APIAWS 管理主控台，將 RDS Custom for SQL Server 資料庫執行個體還原至某個時間點。

### 主控台
<a name="custom-backup-sqs.pitr2.CON"></a>

**若要將 RDS Custom 資料庫執行個體還原至指定時間**

1. 登入 AWS 管理主控台並開啟位於 https：//[https://console.aws.amazon.com/rds/](https://console.aws.amazon.com/rds/) 的 Amazon RDS 主控台。

1. 在導覽窗格中，選擇 **Automated backups** (自動備份)。

1. 選擇您想要還原的 RDS Custom 資料庫執行個體。

1. 針對 **Actions** (動作)，選擇 **Restore to point in time** (還原至時間點)。

   **Restore to point in time (還原到時間點)** 視窗隨即出現。

1. 選擇 **Latest restorable time (最近的可還原時間)** 以還原最近一次的可能時間，或選擇 **Custom (自訂)** 以選擇一個時間。

   如果您選擇 **Custom (自訂)**，請輸入您希望執行個體叢集還原到什麼日期和時間。

   會以您的當地時區顯示時間，根據國際標準時間 (UTC) 的時差來表示。例如，UTC-5 是東部標準時間/中部日光節約時間。

1. 對於 **DB Instance Identifier** (資料庫執行個體識別符)，輸入目標還原 RDS Custom 資料庫執行個體的名稱。名稱必須是唯一的。

1. 視需要選擇其他選項，例如資料庫執行個體類別。

1. 選擇 **Restore to point in time (還原至時間點)**。

### AWS CLI
<a name="custom-backup-sqs.pitr2.CLI"></a>

您可以使用 [ restore-db-instance-to-point-in-time](https://docs.aws.amazon.com/cli/latest/reference/rds/restore-db-instance-to-point-in-time.html) AWS CLI 命令來建立新的 RDS Custom 資料庫執行個體，將資料庫執行個體還原至指定時間。

使用下列其中一個選項來指定要從中還原的備份：
+ `--source-db-instance-identifier mysourcedbinstance`
+ `--source-dbi-resource-id dbinstanceresourceID`
+ `--source-db-instance-automated-backups-arn backupARN`

`custom-iam-instance-profile` 選項為必要項目。

下列範例會將 `my-custom-db-instance` 還原至名稱為 `my-restored-custom-db-instance` 的新資料庫執行個體，截至指定的時間。

**Example**  
對於 Linux、macOS 或 Unix：  

```
1. aws rds restore-db-instance-to-point-in-time \
2.     --source-db-instance-identifier my-custom-db-instance\
3.     --target-db-instance-identifier my-restored-custom-db-instance \
4.     --custom-iam-instance-profile AWSRDSCustomInstanceProfileForRdsCustomInstance \
5.     --restore-time 2022-10-14T23:45:00.000Z
```
在 Windows 中：  

```
1. aws rds restore-db-instance-to-point-in-time ^
2.     --source-db-instance-identifier my-custom-db-instance ^
3.     --target-db-instance-identifier my-restored-custom-db-instance ^
4.     --custom-iam-instance-profile AWSRDSCustomInstanceProfileForRdsCustomInstance ^
5.     --restore-time 2022-10-14T23:45:00.000Z
```