すべてのプロダクト
Search
ドキュメントセンター

Data Management:オンプレミスデータベースまたはサードパーティプロバイダのクラウドデータベースをバックアップする

最終更新日:Apr 16, 2025

データディザスタリカバリ は、Alibaba Cloud データベース、Elastic Compute Service (ECS) インスタンスでホストされている自己管理データベース、オンプレミスデータベース、およびサードパーティプロバイダのクラウドデータベースをサポートしています。このトピックでは、オンプレミスデータベースまたはサードパーティプロバイダのクラウドデータベースをバックアップする方法について説明します。

使用上の注意

バックアップ対象のデータベースとテーブルに、不適切なテーブルスキーマ、大きなテーブル、大きなフィールドなどの問題がある場合、バックアップスケジュールに十分なリソースがない可能性があり、バックアップの例外が発生する可能性があります。そのため、後続のバックアップで例外が発生しないように、バックアップスケジュールを作成するときに大きな仕様タイプを選択することをお勧めします。

手順

サービスの自動バックアップ

バックアップスケジュールの購入(論理バックアップ)

  1. DMS コンソール V5.0 にログオンします。

  2. 上部のナビゲーションバーで、[セキュリティと仕様 (DBS)] > [データのディザスタリカバリ (DBS)] > [ディザスタリカバリデータソース] を選択します。

    説明

    シンプルモードで DMS コンソールを使用する場合は、DMS コンソールの左上隅にある 2023-01-28_15-57-17.png アイコンにポインタを移動し、[すべての機能] > [セキュリティと仕様 (DBS)] > [データのディザスタリカバリ (DBS)] > [ディザスタリカバリデータソース] を選択します。

  3. ページの上部で、リージョンを選択します。 [ディザスタリカバリデータソース] ページで、[オンプレミスデータベースとサードパーティプロバイダのクラウドデータベース] > [ユーザーの自動バックアップ] を選択し、使用するデータソースの ID をクリックして詳細ページに移動します。

  4. [バックアップポリシー] ページで、[バックアップポリシーの構成] をクリックします。

  5. [バックアップスケジュールの選択] ステップで、[バックアップスケジュールの購入] をクリックして購入ページに移動します。

  6. 次のパラメータを構成し、ページの右下隅にある [今すぐ購入] をクリックします。

    パラメータ

    説明

    製品タイプ

    バックアップスケジュール を選択します。

    リージョン

    バックアップデータを保存するリージョン。

    説明

    バックアップスケジュールと Elastic Compute Service (ECS) インスタンスが同じリージョンにあることを確認してください。

    データソースタイプ

    MySQL に設定します。

    仕様

    使用するバックアップスケジュールの仕様。仕様が高いほど、バックアップとリストアのパフォーマンスが高くなります。DBS は、micro、small、medium、large、xlarge のバックアップスケジュールの仕様をサポートしています。 xlarge 仕様タイプは、バックアップデータ量の制限がない特大仕様を提供します。

    説明
    • 本番環境のデータベースインスタンスなど、特定のデータベースインスタンスのバックアップとリストアを高速化するには、xlarge または Large を選択することをお勧めします。

    • 高いバックアップおよびリストアパフォーマンスが不要な場合は、ビジネス要件に基づいて最も費用対効果の高いバックアップスケジュールタイプを選択できます。詳細については、「バックアップスケジュールタイプの選択」をご参照ください。

    • バックアップ対象のデータベースとテーブルに、不適切なスキーマ、大きなテーブル、大きなフィールドなどの問題が関係する場合、仕様の低いバックアップインスタンスのリソースではバックアップを完了できない場合があります。その結果、バックアップエラーが発生します。バックアップエラーを防ぐために、より高い仕様のバックアップインスタンスを購入することをお勧めします。

    バックアップ方法

    論理バックアップ を選択します。

    ストレージサイズ

    バックアップスケジュールを作成するときに容量を選択する必要はありません。データディザスタリカバリに保存されているデータ量に基づいて課金されます。詳細については、「ストレージ料金」をご参照ください。

    リソースグループ

    バックアップスケジュールで使用されるリソースグループ。デフォルトのリソースグループを使用するか、ビジネス要件に基づいてリソースグループを選択できます。

    数量

    購入するバックアップスケジュールの数。複数のデータベースインスタンスをバックアップするには、複数のバックアップスケジュールを購入する必要があります。たとえば、データベースインスタンス A とデータベースインスタンス B をバックアップする場合、2 つのバックアップスケジュールを購入する必要があります。

    サブスクリプション期間

    購入するバックアップスケジュールのサブスクリプション期間。

  7. [注文の確認] ページで、注文情報を確認し、サービス条件を読んで選択してから、[支払] をクリックします。

    支払いが完了したら、[バックアップスケジュールの選択] ステップに戻り、[支払済] をクリックして、作成されたバックアップスケジュールを表示します。

    image

バックアップポリシーの構成

  1. [バックアップスケジュールの選択] ステップで、構成するバックアップスケジュールを選択し、[次へ] をクリックします。

    image

  2. [データベースとテーブルの選択] ステップで、バックアップするデータベースとテーブルを選択し、image アイコンをクリックして [選択済みオブジェクト] セクションに移動してから、[送信] をクリックします。

    image..png

  3. [バックアップポリシー] ページで、[論理バックアップ] タブをクリックし、[開始] をクリックしてバックアップを開始します。

    [開始] をクリックすると、システムはすぐに完全バックアップと増分バックアップを開始します。

    image

    説明

    バックアップポリシーの変更など、他の操作を実行する場合は、この手順をスキップできます。データディザスタリカバリは、後でバックアップポリシーに基づいてバックアップを自動的に開始します。

ユーザーの自動バックアップ

重要
  • MySQL 5.5 を実行するデータベースインスタンスのみがサポートされています。

  • 中国 (杭州) リージョンのみがサポートされています。

バックアップソースの構成とバックアップファイルのアップロード

  1. DMS コンソール V5.0 にログオンします。

  2. 上部のナビゲーションバーで、[セキュリティと仕様 (DBS)] > [データのディザスタリカバリ (DBS)] > [ディザスタリカバリデータソース] を選択します。

    説明

    シンプルモードで DMS コンソールを使用する場合は、DMS コンソールの左上隅にある 2023-01-28_15-57-17.png アイコンにポインタを移動し、[すべての機能] > [セキュリティと仕様 (DBS)] > [データのディザスタリカバリ (DBS)] > [ディザスタリカバリデータソース] を選択します。

  3. ページの上部で、リージョンを選択します。 [ディザスタリカバリデータソース] ページで、[オンプレミスデータベースとサードパーティプロバイダのクラウドデータベース] タブをクリックし、データソースタイプに基づいてデータソースを追加します。

  4. [データソースの追加] をクリックします。表示されるダイアログボックスで、次のパラメータを構成し、使用するバックアップスケジュールを選択して、[次へ] をクリックします。

    image

    パラメータ

    説明

    データソース名

    識別しやすい説明的な名前を使用することをお勧めします。

    エンジンの種類

    データベースエンジンの種類。MySQL のみがサポートされています。

    エンジンバージョン

    バックアップするデータベースのエンジンバージョン。

    エンジンパラメータ

    {"lower_case_table_names":1}

    使用可能なバックアップスケジュールがない場合は、[バックアップスケジュールの購入] をクリックして購入ページに移動し、バックアップスケジュールを購入します。

    説明

    製品タイプ

    バックアップスケジュール を選択します。従量課金制はサポートされていません。

    リージョン

    バックアップデータを保存するリージョン。

    データソースタイプ

    MySQL を選択します。

    仕様

    xmicro を選択します。 xmicro 仕様タイプで提供される無料枠の詳細については、「バックアップスケジュールタイプ」をご参照ください。

    バックアップ方法

    物理バックアップ を選択します。

    ストレージサイズ

    バックアップスケジュールを作成するときに容量を選択する必要はありません。データディザスタリカバリ に保存されているデータ量に基づいて課金されます。詳細については、「ストレージ料金」をご参照ください。

    リソースグループ

    バックアップスケジュールで使用されるリソースグループ。デフォルトのリソースグループを使用するか、ビジネス要件に基づいてリソースグループを選択できます。

    数量

    購入するバックアップスケジュールの数。複数のデータベースインスタンスをバックアップするには、複数のバックアップスケジュールを購入する必要があります。たとえば、データベースインスタンス A とデータベースインスタンス B をバックアップする場合、2 つのバックアップスケジュールを購入する必要があります。

    サブスクリプション期間

    購入するバックアップスケジュールのサブスクリプション期間。

  5. 指定されたバケットにバックアップセットをアップロードします。詳細については、「データのアップロード (ユーザーの自動バックアップ)」をご参照ください。

  6. [OK] をクリックします。

バックアップ情報の表示

[ユーザーの自動バックアップ] タブで、管理するデータソースの ID をクリックします。

image

image

バックアップポリシーの構成

  1. [ユーザーの自動バックアップ] タブで、管理するデータソースを見つけ、[操作] 列の [バックアップポリシーの表示] をクリックします。

    image

    image

  2. [OK] をクリックします。

バックアップデータの表示とダウンロード

  1. [ユーザーの自動バックアップ] タブで、管理するデータソースの ID をクリックします。

  2. 左側のナビゲーションウィンドウで、[バックアップデータ] をクリックします。

    説明

    データスクリプトをアップロードしてデータソースを作成した後、新しいバックアップセットが生成されると、システムは自動的にバックアップセットを [バックアップデータ] ページに同期します。

  3. バックアップセットの [操作] 列の [ダウンロード] をクリックして、バックアップセットをダウンロードします。

リストアタスクの作成

説明

データをリストアするには、バックアップセットが [データバックアップ] ページに表示され、完了状態である必要があります。

  1. [ユーザーの自動バックアップ] タブで、管理するデータソースの ID をクリックします。

  2. 左側のナビゲーションウィンドウで、[バックアップデータ] をクリックします。 [論理バックアップ] タブで、[リストアタスクの作成] をクリックして、次のリストアパラメータを構成します。

    パラメータ

    説明

    タスク名

    リストアタスクの名前。識別しやすい説明的な名前を使用することをお勧めします。

    リストア先

    ターゲットデータベースインスタンス。デフォルト値: 新しいインスタンス (RDS)。

    データベースの場所

    ターゲットデータベースインスタンスの場所。デフォルト値: RDS。

    インスタンスリージョン

    ターゲットデータベースインスタンスが存在するリージョン。中国 (杭州) リージョンのみがサポートされています。

    VPC

    ターゲットデータベースインスタンスが存在する VPC。

    VSwitch

    ターゲットデータベースに接続されている vSwitch。

    インスタンスエディション

    ターゲットデータベースインスタンスのエディション。

    インスタンスの仕様

    ターゲットデータベースインスタンスのタイプ。

    ストレージスペース

    ターゲットデータベースインスタンスに必要なストレージスペース。

    リストアモード

    ポイントインタイムでのみデータベースをリストアできます。

    リストア時間

    バックアップセットをリストアするポイントインタイム。使用可能な時間範囲は、リストアモード パラメータの後に表示されます。

  3. 構成が完了したら、[送信] をクリックします。リストアタスクが作成されます。タスク情報は [リストアタスク] ページに表示されます。

リストアタスクの表示

  1. [ユーザーの自動バックアップ] タブで、管理するデータソースの ID をクリックします。

  2. 左側のナビゲーションウィンドウで、[タスク管理] > [リストアタスク] を選択します。

  3. [リストア結果] 列のインスタンス ID をクリックして、バックアップセットのリストア先の RDS インスタンスの [基本情報] ページに移動します。

リカバリルールの表示

  1. [ユーザーの自動バックアップ] タブで、管理するデータソースの ID をクリックします。

  2. 左側のナビゲーションウィンドウで、[リカバリルール] をクリックします。

    リカバリルールのメトリック

    リカバリルールのメトリックは、[リカバリタスクの成功率][平均リカバリ時間][データバックアップルールのカバレッジ率][ログバックアップルールのカバレッジ率] です。

    メトリック

    説明

    リカバリタスクの成功率

    指定された期間内のポイントインタイムにデータをリストアするリストアタスクの成功率。

    平均リカバリ時間

    指定された期間内の成功したリストアタスクの平均時間。

    データバックアップルールのカバレッジ率

    指定された期間内にオープンソースの MySQL インスタンスまたは ApsaraDB RDS for MySQL インスタンスで実行されるデータリカバリルールのカバレッジ率。

    ログバックアップルールのカバレッジ率

    指定された期間内にオープンソースの MySQL インスタンスまたは ApsaraDB RDS for MySQL インスタンスで実行されるログリカバリルールのカバレッジ率。

    リカバリルールのタイムライン

    タイムラインには、指定された期間内の各ポイントインタイムにおけるリカバリルールの詳細が表示されます。タイムラインをクリックすると、現在のポイントインタイムのルール情報が表示されます。

    リカバリルールの詳細

    [データバックアップ] タブをクリックして、データバックアップのリカバリルールの詳細を表示します。 [ルール結果] 列のインスタンス ID をクリックして、リストアされた RDS インスタンスの [基本情報] ページに移動します。

    [ログバックアップ] タブをクリックして、ログバックアップのリカバリルールの詳細を表示します。

データのアップロード (ユーザーの自動バックアップ)

準備

  • データソースを構成し、データソースの ID を取得します。データソースの構成方法の詳細については、「データソースの追加」をご参照ください。

  • RAM ユーザーを作成し、指定されたインスタンスを管理するために必要な権限を RAM ユーザーに付与し、AccessKey ID と AccessKey シークレットを準備します。詳細については、「RAM ユーザーの作成」および「RAM ユーザーへの権限の付与」をご参照ください。

依存関係

  • コマンドツール: Bash および Python3。

  • Python ライブラリ: oss2、alibabacloud_openapi_util、alibabacloud_tea_openapi、および alibabacloud_tea_util。

## Alibaba Cloud SDK をインストールします。
pip3 install --upgrade pip
pip3 install -i https://mirrors.aliyun.com/pypi/simple/ oss2 alibabacloud_openapi_util alibabacloud_tea_openapi alibabacloud_tea_util

完全なスクリプトのアップロード

次のスクリプトを使用してバックアップデータをアップロードする必要があります。

Bash スクリプト

必要に応じて、実際のデータソースパラメータに置き換えます。

boot_backup.sh: xtrabackup ツールを使用して完全バックアップのプロセスをシミュレートします。

#!/bin/bash
# Alibaba Cloud アカウントの AccessKey ペアには、すべての API 操作に対する権限があります。これらの資格情報を使用して操作を実行することは、リスクの高い操作です。 API アクセスまたは日常の O&M には、RAM ユーザーを作成して使用することをお勧めします。
## AccessKey ペアをコードに保存しないでください。キーの漏洩につながる可能性があります。ビジネス要件に基づいて、構成ファイルに Access ペアを保存できます。

AK=<ALIBABA_CLOUD_ACCESS_KEY_ID>
SK=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
DBS_API=dbs-api.<データソースが存在するリージョンの ID。例: cn-hangzhou>.aliyuncs.com
DATASOURCE_ID=<データソース ID>

## スクリプトの現在のパスを取得します。
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

## xtrabackup バックアップコマンドを実行して、エラーログを xtrabackup.log ファイルに出力します。
~/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

## 現在の xtrabackup バックアップのディレクトリを取得します。
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

## データを tar.gz ファイルにパッケージ化します。
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

## Python スクリプトを使用して、バックアップデータをアップロードし、バックアップセットメタデータを登録します。
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 スクリプト

  • upload_and_register_backup_set.py: 完全バックアップとログバックアップのデータをアップロードし、対応するメタデータを解析し、バックアップセットメタデータを登録します。

    # -*- coding: utf-8 -*-
    # このファイルは自動生成されています。編集しないでください。ありがとうございます。
    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="サンプルのコマンドラインパーサー。")
        parser.add_argument("--access_key_id", help="Aliyun AccessKeyId。")
        parser.add_argument("--access_key_secret", help="Aliyun AccessKeySecret。")
        parser.add_argument("--endpoint", help="Aliyun API エンドポイント。")
        parser.add_argument("--region_code", help="Aliyun データソース RegionCode。")
        parser.add_argument("--datasource_id", help="Aliyun DataSourceId。")
        parser.add_argument("--data_type", help="BackupSet データ型: FullBackup | LogBackup。")
        parser.add_argument("--file_path", help="BackupSet ファイルパス。")
        parser.add_argument("--xtrabackup_info_path", help="Xtrabackup 情報パス。")
        parser.add_argument("--xtrabackup_log_path", help="Xtrabackup ログパス。")
        parser.add_argument("--begin_time", help="Binlog 開始時間。")
        parser.add_argument("--end_time", help="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")
        # .time() メソッドを使用して時間タプルを取得し、time.mktime を使用して時間タプルを秒単位のタイムスタンプに変換します。
        timestamp_seconds = time.mktime(dt_obj.timetuple())
        return int(timestamp_seconds) * 1000
    
    
    def create_oss_client(params):
        # Alibaba Cloud Object Storage Service (OSS) 認証情報
        access_key_id = params['AccessKeyId']
        access_key_secret = params['AccessKeySecret']
        security_token = params['SecurityToken']
        bucket_name = params['BucketName']
        endpoint = params['OssEndpoint']
    
        # OSS クライアントを初期化します。
        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):
        """
        マルチパートアップロードタスクを実行して、大きなオブジェクトを OSS にアップロードします。
        :param oss_client:
        : param file_path: ローカルファイルパス。
        : param object_key: OSS のオブジェクトキー。ファイル名です。
        """
        # パートサイズをバイト単位で設定します。デフォルト値は 1 MB です。
        part_size = 1024 * 1024 * 5
        # マルチパートアップロードタスクを開始します。
        upload_id = oss_client.init_multipart_upload(object_key).upload_id
    
        # ファイルを開き、コンテンツを読み取ります。
        with open(file_path, 'rb') as file_obj:
            parts = []
            while True:
                data = file_obj.read(part_size)
                if not data:
                    break
                # パートをアップロードします。
                result = oss_client.upload_part(object_key, upload_id, len(parts) + 1, data)
                parts.append(oss2.models.PartInfo(len(parts) + 1, result.etag))
    
            # マルチパートアップロードを完了します。
            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)
            # エンドポイントの詳細については、https://api.aliyun.com/product/Rds をご覧ください。
            config.endpoint = endpoint
            self.client = OpenApiClient(config)
    
        """
        バックアップセットメタデータを登録します。
        """
        def configure_backup_set_info(self, req_param):
            params = open_api_models.Params(
                # 呼び出す操作。
                action='ConfigureBackupSetInfo',
                # 操作のバージョン番号。
                version='2021-01-01',
                # 操作のプロトコル。
                protocol='HTTPS',
                # 操作の HTTP メソッド。
                method='POST',
                auth_type='AK',
                style='RPC',
                # 操作の URL。
                pathname='/',
                # リクエストボディの形式。
                req_body_type='json',
                # レスポンスボディの形式。
                body_type='json'
            )
            # ランタイムオプション
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # レスポンスは MAP タイプで、レスポンスボディ、レスポンスヘッダー、および HTTP ステータスコードが含まれています。
            print(f"ConfigureBackupSetInfo request: {req_param}")
            data = self.client.call_api(params, request, runtime)
    
            print(f"ConfigureBackupSetInfo response: {data}")
            return data['body']['Data']
    
        """
        OSS アップロード情報を取得します。
        """
        def describe_bak_datasource_storage_access_info(self, req_param):
            params = open_api_models.Params(
                # 呼び出す操作。
                action='DescribeBakDataSourceStorageAccessInfo',
                # 操作のバージョン番号。
                version='2021-01-01',
                # 操作のプロトコル。
                protocol='HTTPS',
                # 操作の HTTP メソッド。
                method='POST',
                auth_type='AK',
                style='RPC',
                # 操作の URL。
                pathname='/',
                # リクエストボディの形式。
                req_body_type='json',
                # レスポンスボディの形式。
                body_type='json'
            )
            # ランタイムオプション
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # レスポンスは MAP タイプで、レスポンスボディ、レスポンスヘッダー、および HTTP ステータスコードが含まれています。
            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'}
    
            # バックアップセットを初めて登録します。バックアップセットの ID が返されます。
            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")
    
            # データを 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")
    
            # バックアップセットがアップロードされたことをマークします。
            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)
    
        # 完全バックアップとログバックアップで異なるメソッドで extraMeta を構築します。
        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}")
    
        # データをアップロードし、バックアップセットメタデータを登録します。
        uploader.upload_and_register_backup_set(file_path=args.file_path, data_type=args.data_type, extra_meta=extra_meta)
  • xtrabackup_info_parser.py: xtrabackup_info ファイルを使用してメタデータを解析します。

    # -*- coding: utf-8 -*-
    # このファイルは自動生成されています。編集しないでください。ありがとうございます。
    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: xtrabackup.log ファイルを使用してメタデータを解析します。

    #!/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):
        """
        指定された日付部分と時間部分に基づいて、完全な日付時刻文字列を解析して返します。
        """
        # 現在の年の最初の 2 桁を取得します。
        current_century = datetime.now().strftime("%Y")[:2]
    
        year_short = date_part[:2]
        # 完全な年を取得します。
        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:
                    # 日付部分と時間部分を抽出します。
                    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 スクリプトの処理

  1. AccessKey ID、AccessKey シークレット、DBS_API エンドポイント、およびデータソース ID を構成します。

    #!/bin/bash
    # Alibaba Cloud アカウントの AccessKey ペアには、すべての API 操作に対する権限があります。これらの資格情報を使用して操作を実行することは、リスクの高い操作です。 API アクセスまたは日常の O&M には、RAM ユーザーを作成して使用することをお勧めします。
    ## AccessKey ペアをコードに保存しないでください。キーの漏洩につながる可能性があります。ビジネス要件に基づいて、構成ファイルに Access ペアを保存できます。
    
    AK=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    SK=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
    DBS_API=dbs-api.<データソースが存在するリージョンの ID。例: cn-hangzhou>.aliyuncs.com
    DATASOURCE_ID=<データソース ID>
  2. xtrabackup バックアップコマンドを実行して、バックアップデータを指定されたディレクトリに保存し、エラーログを xtrabackup.log ファイルに出力します。

    ## スクリプトの現在のパスを取得します。
    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
    
    ## xtrabackup バックアップコマンドを実行して、エラーログを xtrabackup.log ファイルに出力します。
    ~/innobackupex --defaults-file=/etc/my.cnf --user='<データベースアカウント。例: root>' --password='<データベースパスワード。例: root>' --host='<データベース IP アドレス。例: localhost>' --port=<データベースポート番号。例: 3306> --socket='parallel /var/lib/mysql/mysql.sock' --parallel=4 $XTRA_DATA_DIR/ 2>$XTRA_DATA_DIR/xtrabackup.log 
    • xtrabackup.log ファイルは、完全バックアップセットのメタデータを取得するために解析されます。メタデータには、バックアップの開始時刻、バックアップの終了時刻、整合性ポイントインタイム、および対応するバイナリログの名前が含まれます。

    • 制限:

      xtrabackup バックアップコマンドは、圧縮および暗号化パラメータ (--compress --compress-threads および -- encrypt --encrypt-key-file --encrypt-threads) をサポートしていません。 xtrabackup バックアップコマンドを使用する前に、対応するパラメータを削除してください。

  3. gzip 圧縮を使用して、ディレクトリ形式の完全バックアップデータを tar.gz ファイルに圧縮します。

    ## 現在の xtrabackup バックアップのディレクトリを取得します。
    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
    
    ## データを tar.gz ファイルにパッケージ化します。
    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
    • 次の形式でのみバックアップデータをアップロードできます。

      • tar: ディレクトリファイルは tar でパッケージ化されています。

      • tar.gz: ディレクトリファイルは tar でパッケージ化され、gzip で圧縮されています。

    • 注意事項:

      • tar コマンドを実行してファイルをパッケージ化する前に、chmod 755 コマンドを実行してファイルディレクトリの権限を変更する必要があります。

      • フォルダのルートディレクトリに移動してから、tar コマンドを実行してファイルをパッケージ化する必要があります。

  4. upload_and_register_backup_set.py スクリプトを使用して、バックアップデータをアップロードし、バックアップセットメタデータを登録します。

    ## Python スクリプトを使用して、バックアップデータをアップロードし、バックアップセットメタデータを登録します。
    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

    パラメータ

    説明

    --access_key_id

    AccessKey ID。

    --access_key_secret

    AccessKey シークレット。

    --endpoint

    データディザスタリカバリの API 操作のエンドポイント。詳細については、「エンドポイント」をご参照ください。

    --datasource_id

    データディザスタリカバリのデータソースの ID。

    --region_code

    対応するリージョンの情報。

    --data_type

    バックアップデータのタイプ。有効な値: FullBackup および LogBackup。

    --file_path

    完全バックアップデータのパス。

    --xtrabackup_log_path

    xtrabackup コマンドを実行して生成された xtrabackup.log ファイルのパス。

Python スクリプトの処理

  1. main 関数をエントリ関数として使用します。

    data_type パラメータを FullBackug または LogBackup に設定し、メタデータの登録が依存する extra_meta 情報を構築します。

    説明
    • BINLOG_FILE: バイナリログの名前。

    • dataBegin: バックアップの開始時刻。ミリ秒単位。

    • dataEnd: バックアップの終了時刻。ミリ秒単位。

    • consistentTime: バックアップセット内のデータが整合しているポイントインタイム。秒単位。

    • 完全バックアップの extra_meta 形式を次に示します。

      {
        'BINLOG_FILE':'mysql-bin.001',
        'version':'5.5',
        'dataBegin':17274********,
        'dataEnd':17274********,
        'consistentTime':17274********
      }
    • ログバックアップの extra_meta 形式を次に示します。

      {
        'dataBegin':17274********,
        'dataEnd':17274********
      }
  2. OssUploader.upload_and_register_backup_set メソッドを使用して、バックアップデータをアップロードし、バックアップセットメタデータを登録します。

    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)
    
        # 完全バックアップとログバックアップで異なるメソッドで extraMeta を構築します。
        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}")
    
        # データをアップロードし、バックアップセットメタデータを登録します。
        uploader.upload_and_register_backup_set(file_path=args.file_path, data_type=args.data_type, extra_meta=extra_meta)
  3. OssUploader.upload_and_register_backup_set メソッドを使用して、データアップロードプロセスをバックアップします。

    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)
            # エンドポイントの詳細については、https://api.aliyun.com/product/Rds をご覧ください。
            config.endpoint = endpoint
            self.client = OpenApiClient(config)
    
        """
        バックアップセットメタデータを登録します。
        """
        def configure_backup_set_info(self, req_param):
            params = open_api_models.Params(
                # 呼び出す操作。
                action='ConfigureBackupSetInfo',
                # 操作のバージョン番号。
                version='2021-01-01',
                # 操作のプロトコル。
                protocol='HTTPS',
                # 操作の HTTP メソッド。
                method='POST',
                auth_type='AK',
                style='RPC',
                # 操作の URL。
                pathname='/',
                # リクエストボディの形式。
                req_body_type='json',
                # レスポンスボディの形式。
                body_type='json'
            )
            # ランタイムオプション
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # レスポンスは MAP タイプで、レスポンスボディ、レスポンスヘッダー、および HTTP ステータスコードが含まれています。
            print(f"ConfigureBackupSetInfo request: {req_param}")
            data = self.client.call_api(params, request, runtime)
    
            print(f"ConfigureBackupSetInfo response: {data}")
            return data['body']['Data']
    
        """
        OSS アップロード情報を取得します。
        """
        def describe_bak_datasource_storage_access_info(self, req_param):
            params = open_api_models.Params(
                # 呼び出す操作。
                action='DescribeBakDataSourceStorageAccessInfo',
                # 操作のバージョン番号。
                version='2021-01-01',
                # 操作のプロトコル。
                protocol='HTTPS',
                # 操作の HTTP メソッド。
                method='POST',
                auth_type='AK',
                style='RPC',
                # 操作の URL。
                pathname='/',
                # リクエストボディの形式。
                req_body_type='json',
                # レスポンスボディの形式。
                body_type='json'
            )
            # ランタイムオプション
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # レスポンスは MAP タイプで、レスポンスボディ、レスポンスヘッダー、および HTTP ステータスコードが含まれています。
            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'}
    
            # バックアップセットを初めて登録します。バックアップセットの ID が返されます。
            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")
    
            # データを 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")
    
            # バックアップセットがアップロードされたことをマークします。
            params['UploadStatus'] = 'UploadSuccess'
            self.configure_backup_set_info(params)
            print(f"------ configure_backup_set_info success: {file_path}, {data_type}, {params['BackupSetId']}, UploadSuccess\n")