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

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
对象存储 OSS,20GB 3个月
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: --- 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

目录
相关文章
|
2月前
|
存储 关系型数据库 MySQL
深入理解MySQL索引:从原理到最佳实践
深入理解MySQL索引:从原理到最佳实践
191 0
|
7月前
|
SQL 存储 关系型数据库
MSSQL之一 数据库系统简介 与SQL Server 2008概述
MSSQL之一 数据库系统简介 与SQL Server 2008概述
85 0
|
7月前
|
SQL
MSSQL系列之十二Sql Server 2005安装
MSSQL系列之十二Sql Server 2005安装
48 0
|
6月前
|
NoSQL 关系型数据库 MySQL
阿里云RDS关系型数据库大全_MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等
阿里云RDS关系型数据库如MySQL版、PolarDB、PostgreSQL、SQL Server和MariaDB等,NoSQL数据库如Redis、Tair、Lindorm和MongoDB
254 0
|
7月前
|
SQL 存储 数据可视化
MSSQL之二 Sql Server中管理库与表
MSSQL之二 Sql Server中管理库与表
54 0
|
2月前
|
监控 关系型数据库 MySQL
MySQL Binlog实战:在生产环境中的应用与最佳实践【实战应用】
MySQL Binlog实战:在生产环境中的应用与最佳实践【实战应用】
35 0
|
4月前
|
SQL Oracle 关系型数据库
选择适合您网站的 SQL 托管:MS SQL Server、Oracle、MySQL 和 MS Ac
如果您希望您的网站能够存储和检索数据,您的Web服务器应该能够访问使用SQL语言的数据库系统。以下是一些常见的SQL托管选项:
51 1
|
4月前
|
SQL 运维 关系型数据库
阿里云DTS踩坑经验分享系列|如何使用DTS进行MySQL->ClickHouse同步
在使用阿里云DTS 进行MySQL->ClickHouse同步时,从准备工作,到创建任务,再到后期运维处理,新手可能会感到茫然和不知所措。为了帮助新手顺利过渡,本文将介绍使用阿里云DTS在进行MySQL到ClickHouse迁移时的最佳实践以及常见踩坑问题, 我们希望通过这篇文章,让您能无忧使用阿里云DTS进行数据迁移,享受ClickHouse带来的高效数据分析体验。
98309 12
阿里云DTS踩坑经验分享系列|如何使用DTS进行MySQL->ClickHouse同步
|
4月前
|
SQL Oracle 关系型数据库
选择适合您网站的 SQL 托管:MS SQL Server、Oracle、MySQL
如果您希望您的网站能够存储和检索数据,您的Web服务器应该能够访问使用SQL语言的数据库系统。以下是一些常见的SQL托管选项:
56 2
|
5月前
|
SQL 关系型数据库 分布式数据库
阿里云PolarDB是一款兼容MySQL、PostgreSQL和SQL Server等多种数据库协议的产品
阿里云PolarDB是一款兼容MySQL、PostgreSQL和SQL Server等多种数据库协议的产品
646 6