RDS SQL Server提供了將本地SQL Server資料庫遷移到阿里雲RDS SQL Server的資料庫上雲方案。您只需將本地SQL Server資料庫的全量備份資料上傳至阿里雲的Object Storage Service服務(OSS),然後通過RDS控制台將全量備份資料移轉至指定RDS SQL Server資料庫中。該方案採用微軟官方的備份恢複方案,可保障相容性。適用於資料備份、遷移和災備恢複等情境。
費用說明
本方案中僅會產生OSS的相關費用,詳情如下圖所示。
情境 | 費用說明 |
將本機資料備份檔案上傳至OSS | 不產生費用。 |
備份檔案儲存在OSS | 會產生OSS的儲存費用,計費詳情請參見OSS定價。 |
將備份檔案從OSS遷移至RDS | |
1. 備份本機資料庫
開啟Microsoft SQL Server Management Studio(SSMS)用戶端。
登入待遷移的資料庫。
執行如下命令,確認來源資料庫當前的復原模式。
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
執行如下命令,將來源資料庫的復原模式設定為FULL
。
ALTER DATABASE [dbname] SET RECOVERY FULL;
go
ALTER DATABASE [dbname] SET AUTO_CLOSE OFF;
go
重要 復原模式設定為FULL
後,會使SQL Server的日誌資訊增多,請確保具備足夠的硬碟空間。
執行如下命令,備份來源資料庫。本案例中,將dbtestDatabase Backup至backup.bak檔案中。
USE master;
GO
BACKUP DATABASE [dbtest] to disk ='d:\backup\backup.bak' WITH COMPRESSION,INIT;
GO
執行如下命令,校正備份檔案的完整性。
USE master
GO
RESTORE FILELISTONLY
FROM DISK = N'D:\backup\backup.bak';
重要 如果有結果集返回,代表備份檔案有效。
如果提示錯誤,請重新執行備份操作。
可選:執行如下命令,還原資料庫的復原模式。
重要 如果資料庫的復原模式原本就是FULL
,無需執行本步驟。
ALTER DATABASE [dbname] SET RECOVERY SIMPLE;
GO
2. 上傳備份檔案到OSS
重要 如果OSS中已經建立了Bucket,請檢查Bucket是否滿足如下要求:
建立儲存空間Bucket。
登入OSS管理主控台。
單擊Bucket列表,然後單擊建立Bucket。
配置如下關鍵參數,其他參數可以保持預設。
參數 | 說明 | 取值樣本 |
Bucket 名稱 | 儲存空間名稱,全域唯一,設定後無法修改。 命名規則: 只能包括小寫字母、數字和短劃線(-)。 必須以小寫字母或者數字開頭和結尾。 長度必須在3~63字元之間。
| migratetest |
地區 | Bucket所屬的地區,如果您通過ECS內網上傳資料至Bucket中,且通過內網將資料恢複至RDS中,則需要三者地區保持一致。 | 華東1(杭州) |
儲存類型 | 選擇標準儲存。本文上雲操作不支援其他儲存類型的Bucket。 | 標準儲存 |
上傳備份檔案到OSS。
說明 當RDS執行個體和OSS的Bucket在同一地區時,二者可以通過內網互連,且資料上傳速度更快,並且不會產生外網流量費用。因此,在上傳備份檔案時,建議將檔案上傳至與目標RDS執行個體在同一地區的Bucket上。
本機資料庫備份完成後,需要將備份檔案上傳到您的OSS Bucket中,您可以採用如下方法之一:
使用ossbrowser工具上傳(推薦)
下載ossbrowser。
以Windows x64作業系統為例,解壓下載的oss-browser-win32-x64.zip
壓縮包,雙擊運行oss-browser.exe
應用程式。
使用AK登入方式,配置參數AccessKeyId和AccessKeySecret,其他參數保持預設,然後單擊登入。
說明 AccessKey用於身分識別驗證,確保資料安全,請妥善保管,如何建立及擷取,請參見建立AccessKey。
單擊目標Bucket,進入儲存空間。
單擊,選擇需要上傳的備份檔案,然後單擊開啟,即可將本地檔案上傳至OSS中。
使用OSS控制台上傳
說明 如果備份檔案小於5 GB,建議您直接通過OSS控制台上傳備份檔案。
登入OSS管理主控台。
單擊Bucket列表,然後單擊目標Bucket名稱。
在檔案清單中,單擊上傳檔案。
您可以將備份檔案拖拽至待上傳檔案地區,也可以單擊掃描檔案,選擇需要上傳的備份檔案。
單擊頁面下方的上傳檔案,即可將本地備份檔案上傳至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";
// 填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為cn-hangzhou。
String region = "cn-hangzhou";
// 建立OSSClient執行個體。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
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();
}
}
}
}
設定備份檔案的連結有效時間,並擷取檔案的連結地址。
登入OSS 管理主控台。
單擊Bucket 列表,然後單擊目標Bucket名稱。
在左側導覽列,選擇檔案管理 > 檔案清單。
單擊目標Database Backup檔案的檔案名稱。
在彈出的詳情面板中,將到期時間 (秒)修改為28800秒,即8小時。
重要 將備份檔案從OSS遷移至RDS時,需要使用備份檔案的連結地址,如果超過了連結有效時間,將導致資料移轉失敗。
單擊複製檔案URL,擷取檔案的連結地址。
修改擷取到的資料備份檔案連結地址。
預設擷取的是檔案的外網串連地址,如需通過內網遷移資料,您需要將檔案連結地址中的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
。
3. 將備份檔案從OSS遷移至RDS
訪問RDS執行個體列表,在上方選擇地區,然後單擊目標執行個體ID。
在左側導覽列,單擊資料庫管理。
找到目標資料庫,單擊操作列的從OSS上的備份檔案遷入。
在資料匯入嚮導對話方塊中,閱讀提示內容,單擊下一步。
閱讀OSS上傳的相關提示內容,單擊下一步。
在備份檔案OSS URL欄中填寫備份檔案在OSS的連結地址,單擊確定。
說明 RDS SQL Server 2008 R2本地碟執行個體當前僅支援將全量備份檔案一次性遷入雲上的方案。
4. 查看資料上雲進度
您可以在左側導覽列,單擊資料上雲,然後找到目標遷移任務來查看資料移轉的進度。
重要 如果任務狀態顯示為失敗,請查看任務描述或單擊目標遷移任務後面的查看檔案詳情,確認任務失敗的原因並修複,然後重新執行資料移轉。