by Raj Jayakrishnan Alvaro CostaNeto Nirmal John 和 Vijayakumar Kesavan于2024年7月30日发布 在使用 Amazon Relational Database Service (Amazon RDS) for SQL Server 进行大型关键任务 SQL Server 数据库迁移时,客户们希望在尽量减少停机时间的情况下,将数据库迁移到 AWS,并保持相同的数据库引擎同类迁移。有多种方法可实现自管 SQL Server 向 Amazon RDS for SQL Server 的迁移,包括 原生备份与还原 和 AWS 数据库迁移服务 (AWS DMS)。在任何关键任务数据库迁移中,实施回退策略是一个关键方面。 客户希望在从自管环境迁移至 Amazon RDS for SQL Server 过程中,能够满足其恢复点目标 (RPO) 和恢复时间目标 (RTO) 要求的合适解决方案。接下来,我们讨论如何利用 SQL 的原生备份和恢复选项,设置从 Amazon RDS for SQL Server包括启用和未启用 TDE 的数据库到自管 SQL Server 的前滚回退策略。 全面的回退策略对于数据迁移至关重要,要求细致的规划和应急措施,以降低风险并确保平稳过渡。尽管经过谨慎规划,迁移过程中仍可能出现意外问题,例如数据库性能下降或应用程序失败。能够迅速恢复数据库到先前状态的回退策略显得尤为重要。前滚方法是一种 回退策略,它涉及将数据从迁移后的数据库复制到第三个数据库环境,而不影响源数据库环境。通过在您的迁移策略中纳入数据库回退,您能够确保业务连续性、降低风险,并更有信心地应对意外挑战。这为成功迁移提供了安全保障,保护您宝贵的数据。 以下示意图展示了使用原生备份与还原的前滚方法在 RDS for SQL Server 中的架构。 A 自管 SQL Server,为迁移的源。它可以运行在本地服务器或 Amazon Elastic Compute Cloud (Amazon EC2) 实例上。 B Amazon RDS for SQL Server,为迁移的目标。 A’ 自管 SQL Server,为回退的前滚目标。 您可以根据应用的 RTO 和 RPO 要求,通过不同的方法将自管 SQL Server 环境迁移至 Amazon RDS for SQL Server。您可以选择使用 AWS 数据库迁移服务 (AWS DMS) 或 SQL Server 的原生备份和还原方法,将启用和未启用 TDE 的数据库迁移至 Amazon RDS for SQL Server。本文中的解决方案假设您已使用以上任一方法迁移了 启用 TDE 的 和 未启用 TDE 的 数据库。 您可以按照以下步骤实施启用和未启用 TDE 的数据库的前滚方法: 该解决方案使用已安装 SQL Server 数据库引擎的 Amazon EC2 实例模拟自管环境,Amazon RDS for SQL Server 作为迁移的源。 在开始之前,需要以下前提条件: pythonimport base64from CryptodomeCipher import AESimport sysimport boto3import jsonimport os import requests def unpad(data) padsize = ord(data[1]) return data[padsize] def decrypt(key ivp inputfilename) blocksize = AESblocksize chunksize = blocksize 1024 iv = base64b64decode(ivp) def splits3path(s3path) pathparts = s3pathreplace(s3// )split(/) bucket = pathpartspop(0) key = /join(pathparts) return bucket key def getinfo(bucketname key) filename = keysplit(/)[1] s3 = boto3client(s3) s3response = s3headobject(Bucket=bucketname Key=key) s3metadata = s3response[Metadata] xamzkey = base64b64decode(s3metadata[xamzkey]) dbresourceid = s3metadata[dbresourceid] kmskey = jsonloads(s3metadata[xamzmatdesc])[kmscmkid] xamziv = s3metadata[xamziv] kms = boto3client(kms regionname) kmsoutput = kmsdecrypt( CiphertextBlob=xamzkey KeyId=kmskey EncryptionContext={awsrdsdbid dbresourceid} ) plaintext = kmsoutput[Plaintext] return plaintext xamziv filename def downloadtlog(objectdir startseqid) bucket key = splits3path(objectdir) s3client = boto3client(s3) objects = s3clientlistobjectsv2(Bucket=bucket Prefix=key) def getregion() r = requestsget(http//169254169254/latest/dynamic/instanceidentity/document timeout=10) responsejson = rjson() return responsejsonget(region) def usage() print(Script to download and decrypt the transaction log files from S3 bucket) print(Script to decrypt password for certificate) print(For downloading the tlogs use the following command options) print(Usage python decryptfilepy tlog ) print(For decrypting the password for certificate use the following command options) print(Usage python decryptfilepy certificate ) sysexit(1) def getpassword(certificateuri kmskey) s3 = boto3client(s3) bucketname key = splits3path(certificateuri) s3response = s3headobject(Bucket=bucketname Key=key) s3metadata = s3response[Metadata] rdstdepwd = base64b64decode(s3metadata[rdstdepwd]) kms = boto3client(kms regionname) kmsoutput = kmsdecrypt( CiphertextBlob=rdstdepwd KeyId=kmskey ) plaintext = base64b64encode(kmsoutput[Plaintext]) print(Decryption password {}format(plaintextdecode(utf8))) if name == main if len(sysargv) != 4 usage() action = sysargv[1] print(action) if action != certificate and action != tlog print(Unknown action) usage() 对于本文,我们在美国东部北维吉尼亚地区部署所有 AWS 资源。因为此解决方案涉及 AWS 资源设置与利用,可能会对您的账户产生费用。请参见 AWS 定价 获取更多信息。我们强烈建议您在非生产实例中设置此方案并进行端到端验证,然后再在生产环境中实施此方案。 出于安全最佳实践,我们建议创建两个 S3 桶:一个用作数据库备份和事务日志,另一个用于存储 TDE 证书和私钥文件。在本文中,我们创建的桶分别是 ltcertificatebucketnamegt 和 ltdbbackuplogsbucketnamegt。您必须在与 Amazon RDS DB 实例相同的区域中创建这些桶。有关说明,请参阅 创建一个桶。 ltdbbackuplogsbucketnamegt 桶用于复制备份和事务日志。对于事务日志,需要额外的桶配置。请参考 RDS for SQL Server 的事务日志备份访问 并进行以下配置: 如果您已经拥有一个现有的 IAM 角色,可以继续使用该角色,但请确保具备以下信任关系和权限策略。如果您希望手动创建一个新的 IAM 角色,请参考 创建角色以委派权限给 AWS 服务。 本文中,我们创建了一个名为 rdssqlserverfallforwardrole 的角色,并在以下代码块中添加自定义信任策略中的受信任实体。 json{ Version 20121017 Statement [ { Effect Allow Principal { Service rdsamazonawscom } Action stsAssumeRole } ]} 接下来,我们创建了一个自定义管理策略,使用以下示例 Amazon S3 权限策略,并将其列在 IAM 角色内。 json{ Version 20121017 Statement [ { Effect Allow Action s3ListAllMyBuckets Resource } { Effect Allow Action [ s3ListBucket s3GetBucketLocation s3GetBucketACL ] Resource [ arnawss3ltcertificatebucketnamegt arnawss3ltdbbackuplogsbucketnamegt ] } { Effect Allow Action [ s3GetObject s3PutObject s3ListMultipartUploadParts s3AbortMultipartUpload ] Resource [ arnawss3ltcertificatebucketnamegt/ arnawss3ltdbbackuplogsbucketnamegt/ ] } ]} 在与您的 RDS DB 实例相同的区域创建对称密钥。有关说明,请参考 创建对称加密 KMS 密钥。 创建密钥时选择以下选项: 在此步骤中,我们设置启用和未启用 TDE 的数据库(tdedemo和 notdedemo) 从 Amazon RDS for SQL Server 到 EC2 SQL Server 实例的前滚策略。 启用 TDE 的数据库需要将证书备份并还原到 EC2 SQL Server 实例。未启用 TDE 的数据库不需要备份和还原 TDE 证书。 在此步骤中,我们将备份 Amazon RDS for SQL Server 中的 TDE 证书,并将其还原到 EC2 SQL Server 实例。这一步骤仅适用于启用 TDE 的数据库。实施 Amazon RDS for SQL Server 的前滚回退策略
关键要点
本文讨论了如何从自管的 SQL Server 实现从 Amazon RDS for SQL Server (包括启用和未启用 TDE 的数据库) 的回退策略。回退策略采取“前滚”方法,确保数据库迁移过程中能够快速恢复至之前状态,保障数据完整性与降低潜在风险。将提供详细的步骤来实施此策略,包括建立备份、恢复过程及所需的 AWS 设置。采用前滚方法的回退策略
解决方案概述
从自管 SQL Server 迁移至 Amazon RDS for SQL Server
从 Amazon RDS for SQL Server 到自管 SQL Server 的前滚方法
设置 Amazon RDS for SQL Server 的前滚策略的步骤
前提条件
outputfilename = f{inputfilename}outcipher = AESnew(key AESMODECBC iv)with open(inputfilename rb) as inputfile open(outputfilename wb) as outputfile while True encryptedchunk = inputfileread(chunksize) if len(encryptedchunk) == 0 break decryptedchunk = cipherdecrypt(encryptedchunk) outputfilewrite(decryptedchunk if len(inputfilepeek(chunksize)) else unpad(decryptedchunk))print(fFinished decrypting {outputfilename})
for obj in objects[Contents] fname = ospathbasename(obj[Key]) if int(ospathbasename(obj[Key])split()[2]) gt= startseqid s3clientdownloadfile(bucket obj[Key] fname) plaintext iv inputfilename = getinfo(bucket obj[Key]) decrypt(plaintext iv inputfilename)
regionname = getregion()if action == tlog objectdir = sysargv[2] startseqid = int(sysargv[3]) downloadtlog(objectdir startseqid)if action == certificate certificateuri = sysargv[2] kmsarn = sysargv[3] getpassword(certificateuri kmsarn)
创建 S3 桶
创建 IAM 角色和策略以访问 S3 桶
创建对称 KMS 密钥
从 Amazon RDS for SQL Server 设置前滚至 EC2 SQL Server 实例以支持 TDE 和非 TDE 启用的数据库
备份并还原启用 TDE 的数据库证书