全部產品
Search
文件中心

ApsaraDB RDS:全量備份資料上雲(SQL Server 2008 R2本地碟)

更新時間:Jun 19, 2024

RDS SQL Server提供了將本地SQL Server資料庫遷移到阿里雲RDS SQL Server的資料庫上雲方案。您只需將本地SQL Server資料庫的全量備份資料上傳至阿里雲的Object Storage Service服務(OSS),然後通過RDS控制台將全量備份資料移轉至指定RDS SQL Server資料庫中。該方案採用微軟官方的備份恢複方案,可保障相容性。適用於資料備份、遷移和災備恢複等情境。

說明

前提條件

  • RDS SQL Server執行個體版本為2008 R2本地碟。

    說明

    RDS SQL Server 2008 R2雲端硬碟執行個體已停止新售。

  • 在RDS SQL Server執行個體中建立與待遷移的資料庫名稱相同的資料庫。具體操作,請參見建立資料庫和帳號

  • 如果通過RAM使用者登入,則必須滿足以下條件:

    • RAM帳號具備AliyunOSSFullAccess許可權和AliyunRDSFullAccess許可權。如何為RAM使用者授權,請參見通過RAM對OSS進行許可權管理通過RAM對RDS進行許可權管理

    • 阿里雲帳號(主帳號)已授權RDS官方服務帳號可以訪問您OSS的許可權。

    • 所在阿里雲帳號(主帳號)需手動建立權限原則,然後將許可權添加到RAM帳號中。如何建立權限原則,請參見通過指令碼編輯模式建立自訂權限原則

      策略內容如下:

      {
          "Version": "1",
          "Statement": [
              {
                  "Action": [
                      "ram:GetRole"
                  ],
                  "Resource": "acs:ram:*:*:role/AliyunRDSImportRole",
                  "Effect": "Allow"
              }
          ]
      }

注意事項

本方案遷移的層級為資料庫,即每次只能遷移一個資料庫上雲。如果需要遷移多個或所有資料庫,建議採用執行個體級的遷移上雲方案。具體詳情,請參見SQL Server執行個體層級遷移上雲

費用說明

本方案中僅會產生OSS的相關費用,詳情如下圖所示。

情境

費用說明

將本機資料備份檔案上傳至OSS

不產生費用。

備份檔案儲存在OSS

會產生OSS的儲存費用,計費詳情請參見OSS定價

將備份檔案從OSS遷移至RDS

  • 通過內網遷移至RDS,不產生費用。

  • 通過外網遷移至RDS,OSS會產生外網流出流量的費用,計費詳情請參見OSS定價

步驟一:備份本機資料庫

  1. 開啟Microsoft SQL Server Management Studio(SSMS)用戶端。

  2. 登入待遷移的資料庫。

  3. 執行如下命令,確認來源資料庫當前的復原模式。

    USE master;
    GO
    SELECT name, CASE recovery_model
    WHEN 1 THEN 'FULL'
    WHEN 2 THEN 'BULK_LOGGED'
    WHEN 3 THEN 'SIMPLE' END model FROM sys.databases
    WHERE name NOT IN ('master','tempdb','model','msdb');
    GO
    • 如果返回結果中的model值不為FULL,請執行步驟4。

    • 如果返回結果中的model值為FULL,請執行步驟5。

  4. 執行如下命令,將來源資料庫的復原模式設定為FULL

    ALTER DATABASE [dbname] SET RECOVERY FULL;
    go
    ALTER DATABASE [dbname] SET AUTO_CLOSE OFF;
    go
    重要

    復原模式設定為FULL後,會使SQL Server的日誌資訊增多,請確保具備足夠的硬碟空間。

  5. 執行如下命令,備份來源資料庫。本案例中,將dbtestDatabase Backup至backup.bak檔案中。

    USE master;
    GO
    BACKUP DATABASE [dbtest] to disk ='d:\backup\backup.bak' WITH COMPRESSION,INIT;
    GO
  6. 執行如下命令,校正備份檔案的完整性。

    USE master
     GO
     RESTORE FILELISTONLY 
       FROM DISK = N'D:\backup\backup.bak';
    重要
    • 如果有結果集返回,代表備份檔案有效。

    • 如果提示錯誤,請重新執行備份操作。

  7. 可選:執行如下命令,還原資料庫的復原模式。

    重要

    如果資料庫的復原模式原本就是FULL,無需執行本步驟。

    ALTER DATABASE [dbname] SET RECOVERY SIMPLE;
    GO

步驟二:上傳備份檔案到OSS

重要

如果OSS中已經建立了Bucket,請檢查Bucket是否滿足如下要求:

  • 請確儲存儲備份檔案的OSS Bucket儲存類型為標準儲存。不能是低頻訪問儲存、Archive Storage、冷Archive Storage、深度冷Archive Storage。更多詳情,請參見儲存類型概述

  • 請確保Bucket未開啟資料加密。更多詳情,請參見資料加密

  1. 建立儲存空間Bucket。

    1. 登入OSS管理主控台

    2. 單擊Bucket列表,然後單擊建立Bucket

    3. 配置如下關鍵參數,其他參數可以保持預設。

      重要
      • 建立的儲存空間僅用於本次資料上雲,且上雲後不再使用,因此只需配置關鍵參數即可,為避免資料泄露及產生相關費用,上雲完成後請及時刪除。

      • 建立Bucket時請勿開啟資料加密。更多詳情,請參見資料加密

      參數

      說明

      取值樣本

      Bucket 名稱

      儲存空間名稱,全域唯一,設定後無法修改。

      命名規則:

      • 只能包括小寫字母、數字和短劃線(-)。

      • 必須以小寫字母或者數字開頭和結尾。

      • 長度必須在3~63字元之間。

      migratetest

      地區

      Bucket所屬的地區,如果您通過ECS內網上傳資料至Bucket中,且通過內網將資料恢複至RDS中,則需要三者地區保持一致。

      華東1(杭州)

      儲存類型

      選擇標準儲存。本文上雲操作不支援其他儲存類型的Bucket。

      標準儲存

  2. 上傳備份檔案到OSS。

    說明

    當RDS執行個體和OSS的Bucket在同一地區時,二者可以通過內網互連,且資料上傳速度更快,並且不會產生外網流量費用。因此,在上傳備份檔案時,建議將檔案上傳至與目標RDS執行個體在同一地區的Bucket上。

    本機資料庫備份完成後,需要將備份檔案上傳到您的OSS Bucket中,您可以採用如下方法之一:

    使用ossbrowser工具上傳(推薦)

    1. 下載ossbrowser

    2. 以Windows x64作業系統為例,解壓下載的oss-browser-win32-x64.zip壓縮包,雙擊運行oss-browser.exe應用程式。

    3. 使用AK登入方式,配置參數AccessKeyIdAccessKeySecret,其他參數保持預設,然後單擊登入登入ossbrowser

      說明

      AccessKey用於身分識別驗證,確保資料安全,請妥善保管,如何建立及擷取,請參見建立AccessKey

    4. 單擊目標Bucket,進入儲存空間。進入bucket中

    5. 單擊上傳表徵圖,選擇需要上傳的備份檔案,然後單擊開啟,即可將本地檔案上傳至OSS中。

    使用OSS控制台上傳

    說明

    如果備份檔案小於5 GB,建議您直接通過OSS控制台上傳備份檔案。

    1. 登入OSS管理主控台

    2. 單擊Bucket列表,然後單擊目標Bucket名稱。網頁進入bucket

    3. 檔案清單中,單擊上傳檔案網頁上傳檔案

    4. 您可以將備份檔案拖拽至待上傳檔案地區,也可以單擊掃描檔案,選擇需要上傳的備份檔案。網頁掃描檔案

    5. 單擊頁面下方的上傳檔案,即可將本地備份檔案上傳至OSS中。

    使用OSS API分區上傳

    說明

    如果備份檔案大於5 GB,建議您調用OSS API採用分區上傳的方式將備份檔案上傳到OSS Bucket中。

    本樣本以Java專案為例,從環境變數中擷取訪問憑證代碼。運行本程式碼範例之前,請先配置環境變數。如何配置訪問憑證,請參見配置訪問憑證。更多樣本,請參見分區上傳

    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.common.auth.*;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.internal.Mimetypes;
    import com.aliyun.oss.model.*;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            // Endpoint以華東1(杭州)為例,其它Region請按實際情況填寫。
            String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // 填寫Bucket名稱,例如examplebucket。
            String bucketName = "examplebucket";
            // 填寫Object完整路徑,例如exampledir/exampleobject.txt。Object完整路徑中不能包含Bucket名稱。
            String objectName = "exampledir/exampleobject.txt";
            // 待上傳本地檔案路徑。
            String filePath = "D:\\localpath\\examplefile.txt";
    
            // 建立OSSClient執行個體。
            OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
            try {
                // 建立InitiateMultipartUploadRequest對象。
                InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
    
                // 如果需要在初始化分區時佈建要求頭,請參考以下範例程式碼。
                 ObjectMetadata metadata = new ObjectMetadata();
                // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
                // 指定該Object的網頁緩衝行為。
                // metadata.setCacheControl("no-cache");
                // 指定該Object被下載時的名稱。
                // metadata.setContentDisposition("attachment;filename=oss_MultipartUpload.txt");
                // 指定該Object的內容編碼格式。
                // metadata.setContentEncoding(OSSConstants.DEFAULT_CHARSET_NAME);
                // 指定初始化分區上傳時是否覆蓋同名Object。此處設定為true,表示禁止覆蓋同名Object。
                // metadata.setHeader("x-oss-forbid-overwrite", "true");
                // 指定上傳該Object的每個part時使用的伺服器端加密方式。
                // metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
                // 指定Object的密碼編譯演算法。如果未指定此選項,表明Object使用AES256密碼編譯演算法。
                // metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_DATA_ENCRYPTION, ObjectMetadata.KMS_SERVER_SIDE_ENCRYPTION);
                // 指定KMS託管的使用者主要金鑰。
                // metadata.setHeader(OSSHeaders.OSS_SERVER_SIDE_ENCRYPTION_KEY_ID, "9468da86-3509-4f8d-a61e-6eab1eac****");
                // 指定Object的儲存類型。
                // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard);
                // 指定Object的對象標籤,可同時設定多個標籤。
                // metadata.setHeader(OSSHeaders.OSS_TAGGING, "a:1");
                // request.setObjectMetadata(metadata);
    
                // 根據檔案自動化佈建ContentType。如果不設定,ContentType預設值為application/oct-srream。
                if (metadata.getContentType() == null) {
                    metadata.setContentType(Mimetypes.getInstance().getMimetype(new File(filePath), objectName));
                }
    
                // 初始化分區。
                InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
                // 返回uploadId。
                String uploadId = upresult.getUploadId();
                // 根據uploadId執行取消分區上傳事件或者列舉已上傳分區的操作。
                // 如果您需要根據您需要uploadId執行取消分區上傳事件的操作,您需要在調用InitiateMultipartUpload完成初始化分區之後擷取uploadId。 
                // 如果您需要根據您需要uploadId執行列舉已上傳分區的操作,您需要在調用InitiateMultipartUpload完成初始化分區之後,且在調用CompleteMultipartUpload完成分區上傳之前擷取uploadId。
                // System.out.println(uploadId);
    
                // partETags是PartETag的集合。PartETag由分區的ETag和分區號組成。
                List<PartETag> partETags =  new ArrayList<PartETag>();
                // 每個分區的大小,用於計算檔案有多少個分區。單位為位元組。
                final long partSize = 1 * 1024 * 1024L;   //1 MB。
    
                // 根據上傳的資料大小計算分區數。以本地檔案為例,說明如何通過File.length()擷取上傳資料的大小。
                final File sampleFile = new File(filePath);
                long fileLength = sampleFile.length();
                int partCount = (int) (fileLength / partSize);
                if (fileLength % partSize != 0) {
                    partCount++;
                }
                // 遍曆分區上傳。
                for (int i = 0; i < partCount; i++) {
                    long startPos = i * partSize;
                    long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
                    UploadPartRequest uploadPartRequest = new UploadPartRequest();
                    uploadPartRequest.setBucketName(bucketName);
                    uploadPartRequest.setKey(objectName);
                    uploadPartRequest.setUploadId(uploadId);
                    // 設定上傳的分區流。
                    // 以本地檔案為例說明如何建立FIleInputstream,並通過InputStream.skip()方法跳過指定資料。
                    InputStream instream = new FileInputStream(sampleFile);
                    instream.skip(startPos);
                    uploadPartRequest.setInputStream(instream);
                    // 設定分區大小。除了最後一個分區沒有大小限制,其他的分區最小為100 KB。
                    uploadPartRequest.setPartSize(curPartSize);
                    // 設定分區號。每一個上傳的分區都有一個分區號,取值範圍是1~10000,如果超出此範圍,OSS將返回InvalidArgument錯誤碼。
                    uploadPartRequest.setPartNumber( i + 1);
                    // 每個分區不需要按順序上傳,甚至可以在不同用戶端上傳,OSS會按照分區號排序組成完整的檔案。
                    UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
                    // 每次上傳分區之後,OSS的返回結果包含PartETag。PartETag將被儲存在partETags中。
                    partETags.add(uploadPartResult.getPartETag());
                }
    
    
                // 建立CompleteMultipartUploadRequest對象。
                // 在執行完成分區上傳操作時,需要提供所有有效partETags。OSS收到提交的partETags後,會逐一驗證每個分區的有效性。當所有的資料分區驗證通過後,OSS將把這些分區組合成一個完整的檔案。
                CompleteMultipartUploadRequest completeMultipartUploadRequest =
                        new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
    
                // 如果需要在完成分區上傳的同時設定檔案存取權限,請參考以下範例程式碼。
                // completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.Private);
                // 指定是否列舉當前UploadId已上傳的所有Part。僅在Java SDK為3.14.0及以上版本時,支援通過服務端List分區資料來合并完整檔案時,將CompleteMultipartUploadRequest中的partETags設定為null。
                // Map<String, String> headers = new HashMap<String, String>();
                // 如果指定了x-oss-complete-all:yes,則OSS會列舉當前UploadId已上傳的所有Part,然後按照PartNumber的序號排序並執行CompleteMultipartUpload操作。
                // 如果指定了x-oss-complete-all:yes,則不允許繼續指定body,否則報錯。
                // headers.put("x-oss-complete-all","yes");
                // completeMultipartUploadRequest.setHeaders(headers);
    
                // 完成分區上傳。
                CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
                System.out.println(completeMultipartUploadResult.getETag());
            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message:" + oe.getErrorMessage());
                System.out.println("Error Code:" + oe.getErrorCode());
                System.out.println("Request ID:" + oe.getRequestId());
                System.out.println("Host ID:" + oe.getHostId());
            } catch (ClientException ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message:" + ce.getMessage());
            } finally {
                if (ossClient != null) {
                    ossClient.shutdown();
                }
            }
        }
    }
  3. 設定備份檔案的連結有效時間,並擷取檔案的連結地址。

    1. 登入OSS 管理主控台

    2. 單擊Bucket 列表,然後單擊目標Bucket名稱。

    3. 在左側導覽列,選擇檔案管理 > 檔案清單

    4. 單擊目標Database Backup檔案的檔案名稱。

    5. 在彈出的詳情面板中,將到期時間 (秒)修改為28800秒,即8小時。

      重要

      將備份檔案從OSS遷移至RDS時,需要使用備份檔案的連結地址,如果超過了連結有效時間,將導致資料移轉失敗。

    6. 單擊複製檔案URL,擷取檔案的連結地址。

      image.png

    7. 修改擷取到的資料備份檔案連結地址。

      預設擷取的是檔案的外網串連地址,如需通過內網遷移資料,您需要將檔案連結地址中的Endpoint改成內網Endpoint。

      例如,備份檔案的連結地址為http://rdstest.oss-cn-shanghai.aliyuncs.com/testmigraterds_20170906143807_FULL.bak?Expires=15141****&OSSAccessKeyId=TMP****,您需要將連結地址中的oss-cn-shanghai.aliyuncs.com修改為oss-cn-shanghai-internal.aliyuncs.com

      重要

      不同的網路類型、不同地區所對應的內網Endpoint不同。具體詳情,請參見訪問網域名稱和資料中心

步驟三:將備份檔案從OSS遷移至RDS

  1. 訪問RDS執行個體列表,在上方選擇地區,然後單擊目標執行個體ID。
  2. 在左側導覽列,單擊資料庫管理

  3. 找到目標資料庫,單擊操作列的從OSS上的備份檔案遷入

  4. 資料匯入嚮導對話方塊中,閱讀提示內容,單擊下一步

  5. 閱讀OSS上傳的相關提示內容,單擊下一步

  6. 備份檔案OSS URL欄中填寫備份檔案在OSS的連結地址,單擊確定

    image.png

    說明

    RDS SQL Server 2008 R2本地碟執行個體當前僅支援將全量備份檔案一次性遷入雲上的方案。

步驟四:查看資料上雲進度

您可以在左側導覽列,單擊資料上雲,然後找到目標遷移任務來查看資料移轉的進度。

重要

如果任務狀態顯示為失敗,請查看任務描述或單擊目標遷移任務後面的查看檔案詳情,確認任務失敗的原因並修複,然後重新執行資料移轉。

相關API

API

描述

CreateMigrateTask

將OSS上的備份檔案還原到RDS SQL Server執行個體,建立資料上雲任務。

CreateOnlineDatabaseTask

開啟RDS SQL Server備份資料上雲任務的資料庫。

DescribeMigrateTasks

查詢RDS SQL Server執行個體備份資料上雲工作清單。

DescribeOssDownloads

查詢RDS SQL Server備份資料上雲任務的檔案詳情。