All Products
Search
Document Center

Data Management:On-premises and third-party cloud database backups

Last Updated:Apr 14, 2026

Data disaster recovery supports databases on Alibaba Cloud, self-managed on ECS, on-premises, or on other clouds.

Notes

If source databases or tables have an inefficient schema, large tables, or large fields, a low-specification backup schedule can lead to insufficient resources and trigger backup exceptions. To avoid this, select a higher specification when you create the backup schedule.

Procedure

Product-automated backup

Purchase logical backup schedule

  1. Log in to DMS 5.0.

  2. In the top navigation bar, choose Security and disaster recovery (DBS) > Data Disaster Recovery (DBS) > Disaster Recovery Data Source.

    Note

    If you use the DMS console in simple mode, move the pointer over the 2023-01-28_15-57-17.png icon in the upper-left corner of the DMS console and choose All Features > Security and disaster recovery (DBS) > Data Disaster Recovery (DBS) > Disaster Recovery Data Source.

  3. Select a region at the top of the page. On the On-premise Database and Cloud Database from Third-party Provider page, click the Product-automated backup tab. Then, click the ID of the target data source to go to its details page.

  4. On the Backup Policies page, click Configure Backup Policy.

  5. On the Select Backup Schedule page, click Purchase Backup Schedule to go to the DBS purchase page.

  6. Configure the following parameters and click Buy Now.

    Parameter

    Description

    Product type

    Select Backup Schedule (Subscription).

    Region

    Select the region where you want to store the backup data.

    Note

    The backup schedule and the ECS instance must be in the same region.

    Data source type

    Currently, only MySQL is supported.

    Specification

    The backup schedule specifications that you want to use. Higher specifications offer higher backup and restoration performance. DBS supports the following backup schedule specifications: micro, small, medium, large, and xlarge. The xlarge specification type provides extra large specifications without an upper limit on the amount of backup data.

    Note
    • If your database instance, such as one in a production environment, requires a high-performance backup schedule to quickly run backup and restoration tasks, we recommend selecting the xlarge or large specification.

    • If you do not have high requirements for backup and restoration performance (speed), you can calculate and select the most cost-effective specification for your backup schedule. For more information, see Select a backup schedule specification.

    • If the databases and tables that you want to back up involve issues such as unreasonable schemas, large tables, and large fields, the resources of a backup instance of lower specifications may be insufficient to complete the backup. As a result, a backup error occurs. We recommend that you purchase a backup instance of higher specifications to prevent backup errors.

    Backup method

    Select Logical Backup.

    Storage space

    You do not need to specify a storage capacity when you create the backup schedule. You are charged based on the amount of data stored in the built-in storage of DBS. For more information about billing, see Storage fees.

    Resource Group

    Select the default or a custom Resource Group to manage your backup schedules.

    Quantity

    Select the required number of backup schedules. You must create a separate backup schedule for each database instance. For example, to back up both Database Instance A and Database Instance B, you must purchase two backup schedules.

    Subscription duration

    Select the subscription duration for the backup schedule.

  7. On the Confirm Order page, confirm the order details, read and select the Terms of Service, and then click Pay.

    After paying, return to the Select Backup Schedule page and click Paid. Your new backup schedule appears.

Configure backup policy

  1. On the Select Backup Schedule page, select the backup schedule that you want to configure and click Next.

  2. On the Select Database and Table page, select the databases or tables to back up, click the image icon to move them to the Selected Objects box, and then click Submit.

  3. After you submit the settings, go to the Backup Policies page. On the Logical Backup tab, click Start to start the backup.

    Clicking Start immediately runs a full and an incremental backup.

    Note

    If you want to perform other operations first, such as modifying the backup policy, you can choose not to start the backup immediately. The system automatically starts the backup later based on the schedule defined in the backup policy.

User-automated backup

Important
  • Only MySQL 5.5 data sources are supported.

  • Only the China (Hangzhou) region is supported.

Configure backup source and upload backup files

  1. Log in to DMS 5.0.

  2. In the top navigation bar, choose Security and disaster recovery (DBS) > Data Disaster Recovery (DBS) > Disaster Recovery Data Source.

    Note

    If you use the DMS console in simple mode, move the pointer over the 2023-01-28_15-57-17.png icon in the upper-left corner of the DMS console and choose All Features > Security and disaster recovery (DBS) > Data Disaster Recovery (DBS) > Disaster Recovery Data Source.

  3. Select a region at the top of the page. On the On-premise Database and Cloud Database from Third-party Provider tab, click the button to add a data source based on its type.

  4. Click Add Data Source. In the dialog box that appears, configure the following parameters, select the target backup schedule, and then click Next.

    Parameter

    Description

    Data source name

    Use a descriptive name for easy identification.

    Engine type

    The type of the database engine. Only MySQL is supported.

    Engine version

    Select the version of the database engine.

    Engine parameters

    {"lower_case_table_names":1}

    If no backup schedule is available, click Purchase Backup Schedule to purchase one.

    Description

    Product type

    Select Backup Schedule (Subscription). The pay-as-you-go billing method is not supported.

    Region

    Select the region where you want to store the backup data.

    Data source type

    Select MySQL.

    Specification

    Select xmicro. For more information about the free data quota provided by this specification, see Backup schedule specifications.

    Backup method

    Select Physical Backup.

    Storage space

    You do not need to specify a storage capacity when you create the backup schedule. You are charged based on the amount of data stored in the built-in storage of DBS. For more information about billing, see Storage fees.

    Resource Group

    Select the default or a custom Resource Group to manage your backup schedules.

    Quantity

    Select the number of backup schedules to purchase based on your needs. You must create a separate backup schedule for each database instance. For example, to back up both Database Instance A and Database Instance B, you must purchase two backup schedules.

    Subscription duration

    Select the subscription duration for the backup schedule.

  5. Upload the backup set to the specified bucket. For more information, see User guide for uploading data for automated backups.

  6. After the upload is complete, click OK.

View backup information

On the User-automated backup tab, click the ID of the target data source.

image

image

Configure backup policy

  1. On the User-automated backup tab, find the target data source and click View Backup Policy in the Actions column.

    image

    image

  2. After you configure the policy, click OK.

View and download backup data

  1. On the User-automated backup tab, click the ID of the target data source.

  2. In the left-side navigation pane, click Backup Data.

    Note

    After you run the script to upload data and create the data source, the system synchronizes each new backup set to the Backup Data page.

  3. Find the target backup set and click Download in the Actions column to obtain a download link and download the backup set to your local computer.

Create restoration task

Note

A restoration task requires a generated backup set on the data backup page with a status of Completed.

  1. On the User-automated backup tab, click the ID of the target data source.

  2. In the left-side navigation pane, click Backup Data. Then, click Create Restore Task and manually configure the restoration parameters.

    Parameter

    Description

    Task name

    Enter a descriptive name for the restoration task for easy identification.

    Restore to

    Select the restoration destination. By default, data is restored to a new ApsaraDB RDS instance.

    Database location

    Select the location of the database. The default value is RDS.

    Instance region

    Select the region of the instance. Currently, only the China (Hangzhou) region is supported.

    VPC

    Select a VPC.

    VSwitch

    Select a VSwitch.

    Instance edition

    Select the edition of the destination instance.

    Instance specifications

    Select the specification of the destination instance.

    Storage space

    Select the required storage space.

    Restore mode

    Select the method to restore data. Only point-in-time recovery is supported.

    Restore time

    Select a point in time to which you want to restore the data. The available time range is displayed next to the Restore Mode parameter.

  3. After you configure the parameters, click Submit. A restoration task is created for the selected point in time and appears in the task list.

View restoration tasks

  1. On the User-automated backup tab, click the ID of the target data source.

  2. In the left-side navigation pane, choose Task Management > Restore Tasks.

  3. Click the instance ID in the Restoration Result column to go to the Basic Information page of the restored ApsaraDB RDS instance.

View recovery drills

  1. On the User-automated backup tab, click the ID of the target data source.

  2. In the left-side navigation pane, click Recovery Drill.

    Recovery drill overview metrics

    The recovery drill overview includes metrics such as Recovery Task Success Rate, Average Recovery Duration, Data Backup Drill Coverage Rate, and Log Backup Drill Coverage Rate.

    Metric

    Description

    Recovery task success rate

    The success rate of restoration tasks that restore data to points in time within the specified time range.

    Average recovery duration

    The average duration of successful restoration tasks within the specified time range.

    Data backup drill coverage rate

    The coverage rate of data recovery drills performed on open source MySQL or ApsaraDB RDS for MySQL instances within the specified time range.

    Log backup drill coverage rate

    The coverage rate of log recovery drills performed on open source MySQL or ApsaraDB RDS for MySQL instances within the specified time range.

    Recovery drill timeline

    The timeline displays the details of recovery drills at different points in time within the specified time range. Click a point on the timeline to view details for that specific drill.

    Data backup drill details

    Click Data Backup to view a list of recovery drill details for data backups. Click the instance ID in the Drill Result column to go to the Basic Information page of the restored RDS instance.

    Click Log Backup to view a list of recovery drill details for log backups.

User-provided data upload

Prerequisites

Dependencies

  • Command-line tools: Bash, Python 3.

  • Python packages: oss2, alibabacloud_openapi_util, alibabacloud_tea_openapi, alibabacloud_tea_util.

## Install the Alibaba Cloud OpenAPI SDK
pip3 install --upgrade pip
pip3 install -i https://mirrors.aliyun.com/pypi/simple/ oss2 alibabacloud_openapi_util alibabacloud_tea_openapi alibabacloud_tea_util

Complete upload scripts

The backup data upload process has two parts:

Bash script

This script is the entry point.

boot_backup.sh: Automates the process of creating a local Xtrabackup full backup.

#!/bin/bash
## The AccessKey pair of an Alibaba Cloud account grants full access to all APIs and poses a high security risk. We strongly recommend that you create and use a RAM user for API calls and daily operations.
## To prevent security risks, do not hard-code your AccessKey ID and AccessKey Secret in your code. We recommend that you store them in a configuration file based on your business requirements.

AK=<YOUR_ACCESS_KEY_ID>
SK=<YOUR_ACCESS_KEY_SECRET>
DBS_API=dbs-api.<your_region_id>.aliyuncs.com
DATASOURCE_ID=<your_data_source_id>

## Get the current path of the script.
BASE_PATH=$(cd `dirname $0`; pwd)

TS=`date +%Y%m%d_%H%M%S`
XTRA_DATA_DIR=~/tool/xtrabackup_data/$TS

mkdir -p $XTRA_DATA_DIR

## Run the innobackupex command to create a backup and redirect error logs to the xtrabackup.log file.
~/innobackupex --defaults-file=/etc/my.cnf --user='root' --password='root' --host='localhost' --port=3306 --socket='/var/lib/mysql/mysql.sock' --parallel=4 $XTRA_DATA_DIR/ 2>$XTRA_DATA_DIR/xtrabackup.log

## Get the directory of the current Xtrabackup backup.
backup_dir=`ls $XTRA_DATA_DIR | grep -v xtrabackup.log | head -n1`
echo -e "\033[33mexecute innobackupex success, backup_dir: $backup_dir" && echo -n -e "\033[0m" && chmod 755 $XTRA_DATA_DIR/$backup_dir

## Package the directory into a .tar.gz file.
cd $XTRA_DATA_DIR/$backup_dir && tar -czvf ../$backup_dir.tar.gz . && file ../$backup_dir.tar.gz
echo -e "\033[33mpackage to $backup_dir.tar.gz" && echo -n -e "\033[0m" && sleep 2

## Call the Python script to upload the backup data and register the backup set metadata.
python3 $BASE_PATH/upload_and_register_backup_set.py --access_key_id $AK --access_key_secret $SK --endpoint $DBS_API --datasource_id $DATASOURCE_ID --region_code=cn-hangzhou --data_type=FullBackup --file_path=$XTRA_DATA_DIR/$backup_dir.tar.gz --xtrabackup_log_path=$XTRA_DATA_DIR/xtrabackup.log

Python scripts

  • upload_and_register_backup_set.py: Uploads full backup and log backup data, parses the corresponding metadata, and registers the backup set metadata.

    # -*- coding: utf-8 -*-
    # This file is auto-generated, don't edit it. Thanks.
    import os
    import argparse
    import re
    import time
    import json
    from datetime import datetime
    
    import oss2
    from alibabacloud_openapi_util.client import Client as OpenApiUtilClient
    from alibabacloud_tea_openapi import models as open_api_models
    from alibabacloud_tea_openapi.client import Client as OpenApiClient
    from alibabacloud_tea_util import models as util_models
    
    import xtrabackup_info_parser
    import xtrabackup_log_parser
    
    def init_command_args():
        parser = argparse.ArgumentParser(description="A sample command-line parser.")
        parser.add_argument("--access_key_id", help="Your Alibaba Cloud AccessKey ID.")
        parser.add_argument("--access_key_secret", help="Your Alibaba Cloud AccessKey Secret.")
        parser.add_argument("--endpoint", help="The API endpoint for Alibaba Cloud.")
        parser.add_argument("--region_code", help="The region ID of the data source.")
        parser.add_argument("--datasource_id", help="The ID of the data source.")
        parser.add_argument("--data_type", help="The type of the backup set: FullBackup or LogBackup.")
        parser.add_argument("--file_path", help="The path to the backup set file.")
        parser.add_argument("--xtrabackup_info_path", help="The path to the xtrabackup_info file.")
        parser.add_argument("--xtrabackup_log_path", help="The path to the xtrabackup.log file.")
        parser.add_argument("--begin_time", help="The start time of the binlog.")
        parser.add_argument("--end_time", help="The end time of the binlog.")
    
        args = parser.parse_args()
        if args.access_key_id:
            print(f"access_key_id: ************")
        if args.access_key_secret:
            print(f"access_key_secret: ************")
        if args.endpoint:
            print(f"endpoint: {args.endpoint}")
        if args.region_code:
            print(f"region_code: {args.region_code}")
        if args.datasource_id:
            print(f"datasource_id: {args.datasource_id}")
        if args.data_type:
            print(f"data_type: {args.data_type}")
        if args.file_path:
            print(f"file_path: {args.file_path}")
        if args.xtrabackup_info_path:
            print(f"xtrabackup_info_path: {args.xtrabackup_info_path}")
        if args.xtrabackup_log_path:
            print(f"xtrabackup_log_path: {args.xtrabackup_log_path}")
        if args.begin_time:
            print(f"begin_time: {args.begin_time}")
        if args.end_time:
            print(f"end_time: {args.end_time}")
    
        print('\n')
        return args
    
    
    def date_to_unix_timestamp(date_str):
        dt_obj = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
        # Use `time.mktime` to convert the time tuple from `dt_obj.timetuple()` to a UNIX timestamp in seconds.
        timestamp_seconds = time.mktime(dt_obj.timetuple())
        return int(timestamp_seconds) * 1000
    
    
    def create_oss_client(params):
        # Alibaba Cloud OSS authentication information.
        access_key_id = params['AccessKeyId']
        access_key_secret = params['AccessKeySecret']
        security_token = params['SecurityToken']
        bucket_name = params['BucketName']
        endpoint = params['OssEndpoint']
    
        # Initialize the OSS client.
        auth = oss2.StsAuth(access_key_id, access_key_secret, security_token)
        return oss2.Bucket(auth, endpoint, bucket_name)
    
    
    def upload_oss_file(oss_client, file_path, object_key):
        """
        Uploads a large file to OSS using multipart upload.
        :param oss_client: The OSS client instance.
        :param file_path: The path to the local file.
        :param object_key: The object key in OSS, which is the name of the file.
        """
        # Set the part size in bytes. Default is 5 MB.
        part_size = 1024 * 1024 * 5
        # Initialize the multipart upload.
        upload_id = oss_client.init_multipart_upload(object_key).upload_id
    
        # Open the file and read its content.
        with open(file_path, 'rb') as file_obj:
            parts = []
            while True:
                data = file_obj.read(part_size)
                if not data:
                    break
                # Upload a part.
                result = oss_client.upload_part(object_key, upload_id, len(parts) + 1, data)
                parts.append(oss2.models.PartInfo(len(parts) + 1, result.etag))
    
            # Complete the multipart upload.
            oss_client.complete_multipart_upload(object_key, upload_id, parts)
    
    
    class OssUploader:
    
        def __init__(self, access_key_id, access_key_secret, endpoint, region_code, datasource_id):
            self.access_key_id = access_key_id
            self.access_key_secret = access_key_secret
            self.endpoint = endpoint
            self.region_code = region_code
            self.datasource_id = datasource_id
    
            config = open_api_models.Config(access_key_id, access_key_secret)
            # For more information about endpoints, see https://api.aliyun.com/product/Rds.
            config.endpoint = endpoint
            self.client = OpenApiClient(config)
    
        """
        Registers the backup set metadata.
        """
        def configure_backup_set_info(self, req_param):
            params = open_api_models.Params(
                # The name of the API operation.
                action='ConfigureBackupSetInfo',
                # The version of the API.
                version='2021-01-01',
                # The protocol of the API request.
                protocol='HTTPS',
                # The HTTP method of the API request.
                method='POST',
                auth_type='AK',
                style='RPC',
                # The path of the API request.
                pathname='/',
                # The format of the request body.
                req_body_type='json',
                # The format of the response body.
                body_type='json'
            )
            # Runtime options.
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # Returns a map containing the response body, response headers, and status code.
            print(f"ConfigureBackupSetInfo request: {req_param}")
            data = self.client.call_api(params, request, runtime)
    
            print(f"ConfigureBackupSetInfo response: {data}")
            return data['body']['Data']
    
        """
        Retrieves OSS upload information.
        """
        def describe_bak_datasource_storage_access_info(self, req_param):
            params = open_api_models.Params(
                # The name of the API operation.
                action='DescribeBakDataSourceStorageAccessInfo',
                # The version of the API.
                version='2021-01-01',
                # The protocol of the API request.
                protocol='HTTPS',
                # The HTTP method of the API request.
                method='POST',
                auth_type='AK',
                style='RPC',
                # The path of the API request.
                pathname='/',
                # The format of the request body.
                req_body_type='json',
                # The format of the response body.
                body_type='json'
            )
            # Runtime options.
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # Returns a map containing the response body, response headers, and status code.
            print(f"DescribeBakDataSourceStorageAccessInfo request: {req_param}")
            data = self.client.call_api(params, request, runtime)
    
            print(f"DescribeBakDataSourceStorageAccessInfo response: {data}")
            return data['body']['Data']
    
        def _fetch_oss_access_info(self, params):
            info = self.describe_bak_datasource_storage_access_info({
                'RegionId': params['RegionId'],
                'DataSourceId': params['DataSourceId'],
                'RegionCode': params['RegionCode'],
                'BackupType': params['BackupType'],
                'BackupSetId': params['BackupSetId']
            })
            return info['OssAccessInfo']
    
        def upload_and_register_backup_set(self, file_path, data_type, extra_meta):
            filename = os.path.basename(file_path)
            params = {'BackupMode': 'Automated', 'BackupMethod': 'Physical', 'RegionId': self.region_code,
                      'RegionCode': self.region_code, 'DataSourceId': self.datasource_id, 'BackupSetName': filename,
                      'ExtraMeta': extra_meta, 'BackupType': data_type, 'UploadStatus': 'WaitingUpload'}
    
            # Register the backup set for the first time. The backup set ID is returned.
            data = self.configure_backup_set_info(params)
            params['BackupSetId'] = data['BackupSetId']
            print(f"------ configure_backup_set_info success: {file_path}, {data_type}, {params['BackupSetId']}, WaitingUpload\n")
    
            # Upload the data to OSS.
            oss_info = self._fetch_oss_access_info(params)
            oss_client = create_oss_client(oss_info)
            upload_oss_file(oss_client, file_path, oss_info['ObjectKey'])
            print(f"------ upload_oss_file success: {file_path}, {data_type}, {params['BackupSetId']}\n")
    
            # Mark the backup set as successfully uploaded.
            params['UploadStatus'] = 'UploadSuccess'
            self.configure_backup_set_info(params)
            print(f"------ configure_backup_set_info success: {file_path}, {data_type}, {params['BackupSetId']}, UploadSuccess\n")
    
    
    if __name__ == '__main__':
        args = init_command_args()
        uploader = OssUploader(args.access_key_id, args.access_key_secret,
                               args.endpoint, args.region_code, args.datasource_id)
    
        # Construct extraMeta differently for full backups and log backups.
        extra_meta = '{}'
        if args.data_type == 'FullBackup':
            obj = {}
            if args.xtrabackup_log_path is not None:
                obj = xtrabackup_log_parser.analyze_slave_status(logpath=args.xtrabackup_log_path)
            elif args.xtrabackup_info_path is not None:
                parser = xtrabackup_info_parser.ExtraMetaParser(file_path=args.xtrabackup_info_path)
                obj = parser.get_extra_meta()
            extra_meta = {'BINLOG_FILE': obj.get('BINLOG_FILE'),
                          'version': obj.get("SERVER_VERSION"),
                          'dataBegin': date_to_unix_timestamp(obj.get("START_TIME")),
                          'dataEnd': date_to_unix_timestamp(obj.get("END_TIME")),
                          'consistentTime': int(date_to_unix_timestamp(obj.get("END_TIME")) / 1000)}
            extra_meta = json.dumps(extra_meta)
    
        elif args.data_type == 'LogBackup':
            obj = {'dataBegin': date_to_unix_timestamp(args.begin_time),
                   'dataEnd': date_to_unix_timestamp(args.end_time)}
            extra_meta = json.dumps(obj)
        print(f"get extra meta json string: {extra_meta}")
    
        # Upload the data and register the backup set metadata.
        uploader.upload_and_register_backup_set(file_path=args.file_path, data_type=args.data_type, extra_meta=extra_meta)
  • xtrabackup_info_parser.py: Parses metadata from the xtrabackup_info file.

    # -*- coding: utf-8 -*-
    # This file is auto-generated, don't edit it. Thanks.
    import re
    import json
    
    
    class ExtraMetaParser:
        def __init__(self, file_path):
            self.file_path = file_path
            pass
    
        def _parse_xtrabackup_info(self):
            config_data = {}
            with open(self.file_path, 'r') as file:
                for line in file:
                    line = line.strip()
                    if line and not line.startswith('#'):
                        key, value = line.split('=', 1)
                        config_data[key.strip()] = value.strip()
            return config_data
    
        def get_extra_meta(self):
            config_data = self._parse_xtrabackup_info()
            print(f"xtrabackup_info: {config_data}")
    
            binlog_pos = config_data.get("binlog_pos")
            pattern = f"filename '(.*)', position (.*)"
            match = re.search(pattern, binlog_pos)
    
            return {'BINLOG_FILE': match.group(1),
                    'SERVER_VERSION': config_data.get("server_version"),
                    'START_TIME': config_data.get("start_time"),
                    'END_TIME': config_data.get("end_time")}
  • xtrabackup_log_parser.py: Parses metadata from the xtrabackup.log file generated during the backup.

    #!/usr/bin/python
    # coding:utf8
    
    import io
    import re
    import sys
    from datetime import datetime
    
    from six import binary_type, text_type
    
    
    def parse_date_part(date_part, time_part):
        """
        Parses the given date and time parts and returns a complete date and time string.
        """
        # Get the first two digits of the current year.
        current_century = datetime.now().strftime("%Y")[:2]
    
        year_short = date_part[:2]
        # Construct the full year.
        year_full = current_century + year_short
        date_full = year_full + date_part[2:]
        datetime_str = date_full + " " + time_part
    
        dt = datetime.strptime(datetime_str, "%Y%m%d %H:%M:%S")
        formatted_datetime = dt.strftime("%Y-%m-%d %H:%M:%S")
        return text_type(formatted_datetime)
    
    
    def analyze_slave_status(logpath=None):
        slave_status = {}
        start_time_pattern = (
            r"(\d{6}) (\d{2}:\d{2}:\d{2}) .*Connecting to MySQL server host:"
        )
        """
            240925 17:46:58 completed OK!
            240925 02:22:58 innobackupex: completed OK!
            240925 02:22:58 xtrabackup: completed OK!
        """
        end_time_pattern = r"(\d{6}) (\d{2}:\d{2}:\d{2}) .*completed OK!"
        with io.open(logpath, "rb") as fp:
            lines = fp.read().splitlines()
            for i in reversed(range(len(lines))):
                line = lines[i]
                if isinstance(line, binary_type):
                    line = line.decode("utf-8")
    
                m = re.search(start_time_pattern, line)
                if m:
                    # Extract the date and time parts.
                    date_part = m.group(1)
                    time_part = m.group(2)
                    slave_status["START_TIME"] = parse_date_part(date_part, time_part)
                    continue
    
                m = re.search(r"Using server version (\S*)", line)
                if m:
                    slave_status["SERVER_VERSION"] = text_type(m.group(1))
                    continue
    
                m = re.search("MySQL binlog position:", line)
                if m:
                    binlog_line = line
                    m = re.search(r"filename '(\S*)'", binlog_line)
                    if m:
                        slave_status["BINLOG_FILE"] = text_type(m.group(1))
                    m = re.search(r"position (\d+)", binlog_line)
                    m2 = re.search(r"position '(\d+)'", binlog_line)
                    if m:
                        try:
                            slave_status["BINLOG_POS"] = int(m.group(1))
                        except ValueError:
                            pass
                    elif m2:
                        try:
                            slave_status["BINLOG_POS"] = int(m2.group(1))
                        except ValueError:
                            pass
                    continue
    
                m = re.search("consistent_time (\d+)", line)
                if m:
                    try:
                        slave_status["CONSISTENT_TIME"] = int(m.group(1))
                    except ValueError:
                        pass
                    continue
    
                m = re.search(end_time_pattern, line)
                if m:
                    date_part = m.group(1)
                    time_part = m.group(2)
                    slave_status["END_TIME"] = parse_date_part(date_part, time_part)
                    continue
    
        return slave_status
    
    if __name__ == "__main__":
        logpath = sys.argv[1]
        slave_status = analyze_slave_status(logpath)
        print(slave_status)
    

Bash script workflow

  1. Configure your Alibaba Cloud AccessKey ID and AccessKey Secret, the DBS API endpoint, and the corresponding data source ID.

    #!/bin/bash
    ## The AccessKey pair of an Alibaba Cloud account grants full access to all APIs and poses a high security risk. We strongly recommend that you create and use a RAM user for API calls and daily operations.
    ## To prevent security risks, do not hard-code your AccessKey ID and AccessKey Secret in your code. We recommend that you store them in a configuration file based on your business requirements.
    
    AK=<YOUR_ACCESS_KEY_ID>
    SK=<YOUR_ACCESS_KEY_SECRET>
    DBS_API=dbs-api.<your_region_id>.aliyuncs.com
    DATASOURCE_ID=<your_data_source_id>
  2. Run the innobackupex command to save the backup data to a specified directory and redirect error logs to the xtrabackup.log file.

    ## Get the current path of the script.
    BASE_PATH=$(cd `dirname $0`; pwd)
    
    TS=`date +%Y%m%d_%H%M%S`
    XTRA_DATA_DIR=~/tool/xtrabackup_data/$TS
    
    mkdir -p $XTRA_DATA_DIR
    
    ## Run the innobackupex command to create a backup and redirect error logs to the xtrabackup.log file.
    ~/innobackupex --defaults-file=/etc/my.cnf --user='' --password='' --host='' --port= --socket='/var/lib/mysql/mysql.sock' --parallel=4 $XTRA_DATA_DIR/ 2>$XTRA_DATA_DIR/xtrabackup.log
    • This log file is later parsed to retrieve the metadata of the full backup set, including the backup start time, backup end time, consistent time, and corresponding binlog file name.

    • Limitations:

      The innobackupex command does not support the compression parameters (--compress and --compress-threads) or encryption parameters (--encrypt, --encrypt-key-file, and --encrypt-threads). Remove these parameters from your command.

  3. Compress and package the directory-based full backup data into a .tar.gz file.

    ## Get the directory of the current Xtrabackup backup.
    backup_dir=`ls $XTRA_DATA_DIR | grep -v xtrabackup.log | head -n1`
    echo -e "\033[33mexecute innobackupex success, backup_dir: $backup_dir" && echo -n -e "\033[0m" && chmod 755 $XTRA_DATA_DIR/$backup_dir
    
    ## Package the directory into a .tar.gz file.
    cd $XTRA_DATA_DIR/$backup_dir && tar -czvf ../$backup_dir.tar.gz . && file ../$backup_dir.tar.gz
    echo -e "\033[33mpackage to $backup_dir.tar.gz" && echo -n -e "\033[0m" && sleep 2
    • Limitation: You can only upload backups in file format. The following formats are supported:

      • tar: A directory packaged as a tar archive.

      • tar.gz: A directory packaged as a tar archive and then compressed by using gzip.

    • Notes:

      • Before you use the tar command, run the chmod 755 command to modify the directory permissions.

      • Before running the tar command, navigate to the root of the directory you want to package.

  4. Call the upload_and_register_backup_set.py script to upload the backup data and register its metadata.

    ## Call the Python script to upload the backup data and register the backup set metadata.
    python3 $BASE_PATH/upload_and_register_backup_set.py --access_key_id $AK --access_key_secret $SK --endpoint $DBS_API --datasource_id $DATASOURCE_ID --region_code=cn-hangzhou --data_type=FullBackup --file_path=$XTRA_DATA_DIR/$backup_dir.tar.gz --xtrabackup_log_path=$XTRA_DATA_DIR/xtrabackup.log

    Parameter

    Description

    --access_key_id

    Your Alibaba Cloud AccessKey ID.

    --access_key_secret

    Your Alibaba Cloud AccessKey Secret.

    --endpoint

    The DBS API endpoint.

    --datasource_id

    The ID of your data source.

    --region_code

    The region ID.

    --data_type

    The backup data type. Use FullBackup for a full backup or LogBackup for a log backup.

    --file_path

    The path to the full backup file.

    --xtrabackup_log_path

    The path to the xtrabackup.log file generated for the full backup.

Python script workflow

  1. The main function is the entry point.

    It constructs the extra_meta information required for metadata registration based on the data_type (FullBackup or LogBackup).

    Note
    • BINLOG_FILE: The name of the binlog file.

    • dataBegin: The backup start time as a millisecond-level timestamp.

    • dataEnd: The backup end time as a millisecond-level timestamp.

    • consistentTime: The consistent time as a UNIX timestamp in seconds.

    • Format of extra_meta for a full backup:

      {
        "BINLOG_FILE": "mysql-bin.001",
        "version": "5.5",
        "dataBegin": 17274********,
        "dataEnd": 17274********,
        "consistentTime": 17274********
      }
    • Format of extra_meta for a log backup:

      {
        "dataBegin": 17274********,
        "dataEnd": 17274********
      }
  2. Call the OssUploader.upload_and_register_backup_set method to upload backup data and register its metadata.

    if __name__ == '__main__':
        args = init_command_args()
        uploader = OssUploader(args.access_key_id, args.access_key_secret,
                               args.endpoint, args.region_code, args.datasource_id)
    
        # Construct extraMeta differently for full backups and log backups.
        extra_meta = '{}'
        if args.data_type == 'FullBackup':
            obj = {}
            if args.xtrabackup_log_path is not None:
                obj = xtrabackup_log_parser.analyze_slave_status(logpath=args.xtrabackup_log_path)
            elif args.xtrabackup_info_path is not None:
                parser = xtrabackup_info_parser.ExtraMetaParser(file_path=args.xtrabackup_info_path)
                obj = parser.get_extra_meta()
            extra_meta = {'BINLOG_FILE': obj.get('BINLOG_FILE'),
                          'version': obj.get("SERVER_VERSION"),
                          'dataBegin': date_to_unix_timestamp(obj.get("START_TIME")),
                          'dataEnd': date_to_unix_timestamp(obj.get("END_TIME")),
                          'consistentTime': int(date_to_unix_timestamp(obj.get("END_TIME")) / 1000)}
            extra_meta = json.dumps(extra_meta)
    
        elif args.data_type == 'LogBackup':
            obj = {'dataBegin': date_to_unix_timestamp(args.begin_time),
                   'dataEnd': date_to_unix_timestamp(args.end_time)}
            extra_meta = json.dumps(obj)
        print(f"get extra meta json string: {extra_meta}")
    
        # Upload the data and register the backup set metadata.
        uploader.upload_and_register_backup_set(file_path=args.file_path, data_type=args.data_type, extra_meta=extra_meta)
  3. The following code shows the upload workflow of the OssUploader.upload_and_register_backup_set method.

    class OssUploader:
    
        def __init__(self, access_key_id, access_key_secret, endpoint, region_code, datasource_id):
            self.access_key_id = access_key_id
            self.access_key_secret = access_key_secret
            self.endpoint = endpoint
            self.region_code = region_code
            self.datasource_id = datasource_id
    
            config = open_api_models.Config(access_key_id, access_key_secret)
            # For more information about endpoints, see https://api.aliyun.com/product/Rds.
            config.endpoint = endpoint
            self.client = OpenApiClient(config)
    
        """
        Registers the backup set metadata.
        """
        def configure_backup_set_info(self, req_param):
            params = open_api_models.Params(
                # The name of the API operation.
                action='ConfigureBackupSetInfo',
                # The version of the API.
                version='2021-01-01',
                # The protocol of the API request.
                protocol='HTTPS',
                # The HTTP method of the API request.
                method='POST',
                auth_type='AK',
                style='RPC',
                # The path of the API request.
                pathname='/',
                # The format of the request body.
                req_body_type='json',
                # The format of the response body.
                body_type='json'
            )
            # Runtime options.
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # Returns a map containing the response body, response headers, and status code.
            print(f"ConfigureBackupSetInfo request: {req_param}")
            data = self.client.call_api(params, request, runtime)
    
            print(f"ConfigureBackupSetInfo response: {data}")
            return data['body']['Data']
    
        """
        Retrieves OSS upload information.
        """
        def describe_bak_datasource_storage_access_info(self, req_param):
            params = open_api_models.Params(
                # The name of the API operation.
                action='DescribeBakDataSourceStorageAccessInfo',
                # The version of the API.
                version='2021-01-01',
                # The protocol of the API request.
                protocol='HTTPS',
                # The HTTP method of the API request.
                method='POST',
                auth_type='AK',
                style='RPC',
                # The path of the API request.
                pathname='/',
                # The format of the request body.
                req_body_type='json',
                # The format of the response body.
                body_type='json'
            )
            # Runtime options.
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # Returns a map containing the response body, response headers, and status code.
            print(f"DescribeBakDataSourceStorageAccessInfo request: {req_param}")
            data = self.client.call_api(params, request, runtime)
    
            print(f"DescribeBakDataSourceStorageAccessInfo response: {data}")
            return data['body']['Data']
    
        def _fetch_oss_access_info(self, params):
            info = self.describe_bak_datasource_storage_access_info({
                'RegionId': params['RegionId'],
                'DataSourceId': params['DataSourceId'],
                'RegionCode': params['RegionCode'],
                'BackupType': params['BackupType'],
                'BackupSetId': params['BackupSetId']
            })
            return info['OssAccessInfo']
    
        def upload_and_register_backup_set(self, file_path, data_type, extra_meta):
            filename = os.path.basename(file_path)
            params = {'BackupMode': 'Automated', 'BackupMethod': 'Physical', 'RegionId': self.region_code,
                      'RegionCode': self.region_code, 'DataSourceId': self.datasource_id, 'BackupSetName': filename,
                      'ExtraMeta': extra_meta, 'BackupType': data_type, 'UploadStatus': 'WaitingUpload'}
    
            # Register the backup set for the first time. The backup set ID is returned.
            data = self.configure_backup_set_info(params)
            params['BackupSetId'] = data['BackupSetId']
            print(f"------ configure_backup_set_info success: {file_path}, {data_type}, {params['BackupSetId']}, WaitingUpload\n")
    
            # Upload the data to OSS.
            oss_info = self._fetch_oss_access_info(params)
            oss_client = create_oss_client(oss_info)
            upload_oss_file(oss_client, file_path, oss_info['ObjectKey'])
            print(f"------ upload_oss_file success: {file_path}, {data_type}, {params['BackupSetId']}\n")
    
            # Mark the backup set as successfully uploaded.
            params['UploadStatus'] = 'UploadSuccess'
            self.configure_backup_set_info(params)
            print(f"------ configure_backup_set_info success: {file_path}, {data_type}, {params['BackupSetId']}, UploadSuccess\n")