MSSQL · 最佳实践 · RDS SDK实现数据库迁移上阿里云RDS SQL Server

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
对象存储 OSS,20GB 3个月
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介: --- title: MSSQL · 最佳实践 · RDS SDK实现数据库迁移上阿里云RDS SQL Server author: 风移 --- # 摘要 至今,我们完成了SQL Server备份还原专题系列七篇月报分享:三种常见的数据库备份、备份策略的制定、查找备份链、数据库的三种恢复模式与备份之间的关系、利用文件组实现冷热数据隔离备份方案、如何监控备份还原进度、以及阿里云RD

title: MSSQL · 最佳实践 · RDS SDK实现数据库迁移上阿里云RDS SQL Server

author: 风移

摘要

至今,我们完成了SQL Server备份还原专题系列七篇月报分享:三种常见的数据库备份、备份策略的制定、查找备份链、数据库的三种恢复模式与备份之间的关系、利用文件组实现冷热数据隔离备份方案、如何监控备份还原进度、以及阿里云RDS SQL自动化迁移上云的一种解决方案,本期我们分享如何使用阿里云RDS SDK来实现用户线下数据备份文件迁移上阿里云RDS SQL Server。

适用场景

对于那些不想通过RDS控制台来实现数据库上云RDS SQL Server,具有编程能力的,可以考虑使用RDS SDK来实现线下数据库迁移上云RDS SQL实例上。

实现分析

由于用户线下数据库备份文件位于OSS中,所以迁移上云需要设计到OSS相关的SDK和RDS相关的SDK。

OSS详情

由于用户的线下数据库备份文件存放在OSS上的Bucket中,因此从OSS中获取数据库备份文件需要使用到OSS的SDK;从OSS上获取备份文件的同时,我们还需要知道OSS Bucket所在的Region,因为迁移上云要求RDS实例和OSS Bucket处在同一个Region中。从这些分析来看,我们必须要知道OSS Bucket名字,所在的Endpoint和备份文件名bak_file_key。

RDS详情

RDS实例是指用户需要迁移上云的目标RDS SQL实例,我们需要知道RDS SQL实例的版本信息(RDS SQL 2008R2和2012及以上版本输入参数稍有不同),实例所在的Region(RDS实例需要和OSS Bucket处在同一个Region)以及目标实例上数据库的名字。从分析来看RDS实例,我们需要知道RDS SQL ID和数据库名字。

输入参数

访问阿里云资源,用户需要带上阿里云账户或者子账户的AK,即access_key_id和access_key_secret,因此这两个参数也必不可少。所以,最后我们的输入参数定义为以下七个参数。

access_key_id        :   阿里云用户 access key id

access_key_secret    :   阿里云用户access key secret

rds_instance_id        :   RDS SQL实例ID

database_name        :   目标实例数据库名字

oss_endpoint        :   OSS Endpoint地址

oss_bucket             :   OSS Bucket名

bak_file_key        :   用户备份在OSS Bucket中的文件名

具体实现

实现分析完毕后,以下章节详细介绍具体的实现方法,包括:

准备工作

代码实现

使用方法

准备工作

安装python

首先请根据python官网的引导安装合适的Python版本,推荐安装2.7.10。
安装完毕后,查看Python版本

Windows

C:\>c:\Python27\python.exe -V
Python 2.7.10

上面的输出表明您已经成功安装了Python 2.7.10版本。如果提示“不是内部或外部命令”,请检查配置“环境变量”-“Path”,增加Python的安装路径和pip命令的目录。如图:
01.png

Mac /Linux/Unix

$ python -V
Python 2.7.10

安装SDK依赖包

使用pip安装或者git clone源码安装,任选其一,推荐pip安装,简单方便快捷。

Pip安装

pip install aliyun-python-sdk-rds
pip install oss2

源码安装

# git 克隆openapi
git clone https://github.com/aliyun/aliyun-openapi-python-sdk.git

# 安装阿里云 SDK 核心库
cd aliyun-python-sdk-core
python setup.py install

# 安装阿里云 RDS SDK
cd aliyun-python-sdk-rds
python setup.py install

# git 克隆OSS SDK
git clone https://github.com/aliyun/aliyun-oss-python-sdk.git
cd aliyun-oss-python-sdk

# 安装OSS2
python setup.py install

代码实现

在本文,使用python版RDS SDK实现数据库迁移上云RDS SQL Server,当然你也可以使用C#版、Java版等其他版本,详细的代码实现如下:

#!/usr/bin/python

# -*- coding: utf-8 -*-
"""***************************************************************************************
# Script name    : RdsSQLCreateMigrateTask.py
# Author        : jianming.wjm@alibaba-inc.com
# Create Date   : 2018-06-10 19:27
# Language         : Python 2.7.10
# Dev platform  : Mac OS X 10.12.6

# Purpose        : 
                    This script is for Migration user SQL Server databases localy to alibaba cloud RDS SQL Server.
                    Users' FULL backup files are located on theirselves' OSS Bucket folder already.
                    This script helps users to do migration a offline databases to alibaba cloud RDS SQL Server instance.
                    We achieve those accomplishments by call alibaba cloud RDS OPENAPI.

# Limitation    :
    RDS Edition : Support RDS edition listed below
                    '2008R2', '2012','2012_web','2012_std', '2012_ent', '2012_std_ha', '2012_ent_ha',
                       '2014_web','2014_std', '2014_ent', '2014_std_ha', '2014_ent_ha',
                       '2016_web','2016_std', '2016_ent', '2016_std_ha', '2016_ent_ha'

# Usage         :
    Help         : python RdsSQLCreateMigrateTask.py -h
    Example     : 
                    RdsSQLCreateMigrateTask.py -k <access_key_id> -s <access_key_secret> -i <rds_instance_id> -d <database_name> -e <oss_endpoint> -b <oss_bucket> -f <bak_file_key>
                    
                    variables description
                    access_key_id        :    alibaba cloud user access key id, fg: LTAIKeRvKPRwkaU3
                    access_key_secret    :    alibaba cloud user access key secret, fg: BbZ7xhrertQ0dfgMqfAZPByhnp4G2k
                    rds_instance_id        :   RDS SQL instance ID, fg: rm-2zesz4564ud8s7123
                    database_name        :    The database name will be on RDS.
                    oss_endpoint        :   OSS Endpoint address, fg: oss-cn-beijing.aliyuncs.com
                    oss_bucket             :   OSS Bucket name, fg: test-oss-bucket
                    bak_file_key        :   The backup file key on OSS,fg: Migration/TestMigration_FULL_20180523225534.bak

                : calling example:
                $ python RdsSQLCreateMigrateTask.py -k LTAIKeRvKPRwkaU3 -s BbZ7xhrertQ0dfgMqfAZPByhnp4G2k -i rm-2zesz4564ud8s7123 -d testmigrate -e oss-cn-beijing.aliyuncs.com -b test-oss-bucket -f Migration/TestMigration_FULL_20180523225534.bak


# Output         : There two sesction output, one is the input variables and the other is the migration requests and response.
*********************Input variables*************************************

************************************************************************

*********************Migration requests**********************************

************************************************************************


# Modify Author : jianming.wjm@alibaba-inc.com
# Modify Date   : 2018-06-11 21:43
# Function:
#**************************************************************************************
"""

import json
import os
import sys, getopt
import re
import oss2
import time

from aliyunsdkcore.client import AcsClient
from aliyunsdkrds.request.v20140815 import DescribeMigrateTasksForSQLServerRequest
from aliyunsdkrds.request.v20140815 import CreateMigrateTaskRequest
from aliyunsdkrds.request.v20140815 import DescribeDBInstanceAttributeRequest


def main(argv):
    access_key_id =  access_key_secret =  rds_instance_id =  oss_endpoint =  oss_bucket =  bak_file_key = database_name = ''

    # usage help
    try:
        opts, args = getopt.getopt(argv,"hk:s:i:d:e:b:f:",["access_key_id=", "access_key_secret=", "rds_instance_id=", "database_name=", "oss_endpoint=", "oss_bucket=", "bak_file_key="])
    except getopt.GetoptError:
        print ('%s -k <access_key_id> -s <access_key_secret> -i <rds_instance_id> -d <database_name> -e <oss_endpoint> -b <oss_bucket> -f <bak_file_key>' % (sys.argv[0]))
        sys.exit(2)

    for opt, arg in opts:
        if opt == '-h':
            print ('%s -k <access_key_id> -s <access_key_secret> -i <rds_instance_id> -d <database_name> -e <oss_endpoint> -b <oss_bucket> -f <bak_file_key>' % (sys.argv[0]))
            sys.exit()
        elif opt in ("-k", "-K", "--access_key_id"):
            access_key_id = arg
        elif opt in ("-s", "-S", "--access_key_secret"):
            access_key_secret = arg
        elif opt in ("-i", "-I", "--rds_instance_id"):
            rds_instance_id = arg
        elif opt in ("-d", "-D", "--database_name"):
            database_name = arg
        elif opt in ("-e", "-E", "--oss_endpoint"):
            oss_endpoint = arg
        elif opt in ("-b", "-B", "--oss_bucket"):
            oss_bucket = arg
        elif opt in ("-f", "-F", "--bak_file_key"):
            bak_file_key = arg

    # show the input parameters
       print ("\n*********************Input variables****************************************\n" \
           "access_key_id = %s\naccess_key_secret = %s\nrds_instance_id = %s\ndatabase_name = %s\n" \
           "oss_endpoint = %s\noss_bucket = %s\nbak_file_key = %s\n" \
           "***************************************************************************\n"
           % (access_key_id, access_key_secret, rds_instance_id, database_name, oss_endpoint, oss_bucket, bak_file_key))


       ### check RDS & OSS region to make sure they are located in the same region.

       # get RDS details
       success, rds_details = rds_instnace_details(access_key_id, access_key_secret, rds_instance_id)
       if not success:
           print ("%s" % rds_details)
           sys.exit()

       rds_db_version, rds_engine, rds_region = rds_details["EngineVersion"], rds_details["Engine"], rds_details["RegionId"]

       # get OSS Bucket
       success, oss_details, sign_url = oss_bucket_details(access_key_id, access_key_secret, oss_endpoint, oss_bucket, bak_file_key)
       if not success:
           print ("%s" % oss_details)
           sys.exit()

       oss_region = oss_details.location
       # support db version checking.

       if rds_engine != 'SQLServer' \
           or rds_db_version not in [    '2008r2', '2012','2012_web','2012_std', '2012_ent', '2012_std_ha', '2012_ent_ha',
                                       '2014_web','2014_std', '2014_ent', '2014_std_ha', '2014_ent_ha',
                                       '2016_web','2016_std', '2016_ent', '2016_std_ha', '2016_ent_ha']:
           print("RDS engine doesn't support, this is only for RDS SQL Server engine.")
           sys.exit()

       # RDS & OSS Bucket are not under the same region.
       if not oss_region.endswith(rds_region):
           print("RDS & OSS Bucket are not located in the same region.")
           sys.exit()

       # everything is OK, we'd go to the real business.
       print ("--[%s] will be migrated to your RDS [%s] and the database name will be [%s]." % (bak_file_key, rds_instance_id, database_name))

       # RDS & OSS Bucket are in the same region.
       print ("\n*********************Migration response**********************************")
       do_migrate_database(access_key_id, access_key_secret, rds_instance_id, database_name, oss_endpoint, oss_bucket, bak_file_key, rds_db_version, sign_url)
       print ("************************************************************************")

"""
action to migrate database into RDS
"""
def do_migrate_database(access_key_id, access_key_secret, rds_instance_id, database_name, oss_endpoint, oss_bucket, bak_file_key, rds_db_version, sign_url):
    request = CreateMigrateTaskRequest.CreateMigrateTaskRequest()
    request.set_DBInstanceId(rds_instance_id)
    request.set_DBName(database_name)
    request.set_BackupMode("FULL")
    request.set_IsOnlineDB(True)
    if rds_db_version == '2008r2':
        request.set_DBName(database_name.lower())
        request.set_OSSUrls(sign_url)
    else:
        request.set_OSSUrls("")
        request.set_OssObjectPositions("%s:%s:%s" % (oss_endpoint, oss_bucket, bak_file_key)) # OSSEndpoint:OSSBucket:OSSFileKey
        request.set_CheckDBMode("SyncExecuteDBCheck")

    success, response = _send_request(access_key_id, access_key_secret, request)

    if success:
        print response
    else:
        print ("OPENAPI Response Error !!!!! : %s" % response)


"""
get RDS SQL Instance details via RDS OPENAPI.
"""
def rds_instnace_details(access_key_id, access_key_secret, rds_instance_id):
    request = DescribeDBInstanceAttributeRequest.DescribeDBInstanceAttributeRequest()
    request.set_DBInstanceId(rds_instance_id)
    success, response = _send_request(access_key_id, access_key_secret, request)

    if success:
        if response["Items"]["DBInstanceAttribute"]:
            # print response["Items"]["DBInstanceAttribute"][0]["EngineVersion"]
            # print response["Items"]["DBInstanceAttribute"][0]["RegionId"]
            return True, response["Items"]["DBInstanceAttribute"][0]
        else:
            return False, "Couldn't find specify RDS [%s]." % rds_instance_id
    
    
    return False, response


"""
send request to OPENAPI
and get the response details
"""
def _send_request(access_key_id, access_key_secret, request, region='cn-hangzhou'):
    request.set_accept_format('json')
    try:
        # clt = AcsClient(access_key_id, access_key_secret, 'cn-hangzhou')
        clt = AcsClient(access_key_id, access_key_secret, region)
        response_str = clt.do_action_with_exception(request)
        response_detail = json.loads(response_str)
        return True, response_detail
    except Exception as e:
        return False, e


"""
get OSS Bucket details via OSS OPENAPI
"""
def oss_bucket_details(access_key_id, access_key_secret, oss_endpoint, oss_bucket, bak_file_key):
    try:
        bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), oss_endpoint, oss_bucket)
        bucket_info = bucket.get_bucket_info()
        return True, bucket_info, bucket.sign_url('GET', bak_file_key, 24 * 3600)
    except Exception as e:
        return False, e, None


"""
process entrance main.
"""
if __name__ == '__main__':
    main(sys.argv[1:])

当然,以上代码,你也可以去这里下载以上python脚本。

使用方法

查看Help

你只需要使用-h来查看脚本的使用方法:

$ python ~/Downloads/RdsSQLCreateMigrateTask.py -h
~/Downloads/RdsSQLCreateMigrateTask.py -k <access_key_id> -s <access_key_secret> -i <rds_instance_id> -d <database_name> -e <oss_endpoint> -b <oss_bucket> -f <bak_file_key>

一个例子

以下是一个具体的例子:

$ python ~/Downloads/RdsSQLCreateMigrateTask.py -k LTAIKeRvKPRwkaU3 -s BbZ7xhrertQ0dfgMqfAZPByhnp4G2k -i rm-2zesz4564ud8s7123 -d testmigrate -e oss-cn-beijing.aliyuncs.com -b test-oss-bucket -f Migration/OPENAPIDemo/TestMigration_FULL_20180523225534.bak

输出结果

执行以上命令以后的结果输出,分为三个部分:

第一部分输入参数:展示所有你的输入参数,以便查询输入错误

第二部分提示信息:告诉你,哪一个备份文件会被迁移到哪个实例的哪一个数据库

第三部分调用返回:RDS OPENAPI SDK的返回信息

*********************Input variables****************************************
access_key_id = LTAIKeRvKPRwkaU3
access_key_secret = BbZ7xhrertQ0dfgMqfAZPByhnp4G2k
rds_instance_id = rm-2zesz4564ud8s7123
database_name = testmigrate
oss_endpoint = oss-cn-beijing.aliyuncs.com
oss_bucket = test-oss-bucket
bak_file_key = Migration/OPENAPIDemo/TestMigration_FULL_20180523225534.bak
***************************************************************************

--[Migration/OPENAPIDemo/TestMigration_FULL_20180523225534.bak] will be migrated to your RDS [rm-2zesz4564ud8s7123] and the database name will be [testmigrate].

*********************Migration response**********************************
{u'DBInstanceId': u'rm-2zesz4564ud8s7123', u'BackupMode': u'FULL', u'MigrateTaskId': u'107081', u'RequestId': u'F5419B88-7575-47BA-BDEB-64D280E36C54', u'TaskId': u'70630059', u'DBName': u'testmigrate'}
************************************************************************

最后总结

利用本篇文档,你可以很清楚的了解到使用RDS SDK OPENAPI的最佳实践的同时,又可以实现用户线下数据库迁移上阿里云RDS SQL Server的全自动实现方法。

参考链接

阿里云帮助文档中的CreateMigrateTask

阿里云RDS OPENAPI SDK,在github中的源代码,aliyun-openapi-python-sdk

目录
相关文章
|
8天前
|
SQL 安全 数据库
基于SQL Server事务日志的数据库恢复技术及实战代码详解
基于事务日志的数据库恢复技术是SQL Server中一个非常强大的功能,它能够帮助数据库管理员在数据丢失或损坏的情况下,有效地恢复数据。通过定期备份数据库和事务日志,并在需要时按照正确的步骤恢复,可以最大限度地减少数据丢失的风险。需要注意的是,恢复数据是一个需要谨慎操作的过程,建议在执行恢复操作之前,详细了解相关的操作步骤和注意事项,以确保数据的安全和完整。
19 0
|
11天前
|
前端开发 C# 设计模式
“深度剖析WPF开发中的设计模式应用:以MVVM为核心,手把手教你重构代码结构,实现软件工程的最佳实践与高效协作”
【8月更文挑战第31天】设计模式是在软件工程中解决常见问题的成熟方案。在WPF开发中,合理应用如MVC、MVVM及工厂模式等能显著提升代码质量和可维护性。本文通过具体案例,详细解析了这些模式的实际应用,特别是MVVM模式如何通过分离UI逻辑与业务逻辑,实现视图与模型的松耦合,从而优化代码结构并提高开发效率。通过示例代码展示了从模型定义、视图模型管理到视图展示的全过程,帮助读者更好地理解并应用这些模式。
27 0
|
11天前
|
SQL 数据处理 数据库
|
11天前
|
SQL 存储 调度
|
11天前
|
SQL 安全 数据库
|
11天前
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
32 0
|
SQL 数据库
如何快速备份还原Sql Server 数据库
备份数据库 选择你要备份的数据库,鼠标右键单击,选择任务-备份   弹出备份数据库窗口,选择添加    弹出选择备份目标窗口,点击浏览,选择存放备份数据库的目录,输入文件名,后缀名输入.bak,点击确定,确定,备份完成     还原数据库  鼠标右键单击数据库,选择还原文件和文件   ...
1341 0