日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

云下及他云數(shù)據(jù)庫備份管理

更新時(shí)間:

數(shù)據(jù)災(zāi)備(DBS)除支持阿里云數(shù)據(jù)庫和阿里云ECS自建數(shù)據(jù)庫的災(zāi)備外,還支持對云下及其他云平臺(tái)數(shù)據(jù)庫進(jìn)行災(zāi)備。

注意事項(xiàng)

若備份庫表存在表結(jié)構(gòu)不合理、大表、大字段等情況,備份實(shí)例的規(guī)格過小可能會(huì)導(dǎo)致后續(xù)備份實(shí)例資源不足,從而引發(fā)備份異常。因此,建議您在創(chuàng)建時(shí)選擇較高規(guī)格的備份實(shí)例,以免后續(xù)備份出現(xiàn)異常。

操作步驟

產(chǎn)品自動(dòng)備份

購買備份實(shí)例(邏輯備份)

  1. 登錄數(shù)據(jù)管理DMS 5.0
  2. 在頂部菜單欄中,選擇安全與規(guī)范(DBS) > 數(shù)據(jù)災(zāi)備(DBS) > 災(zāi)備數(shù)據(jù)源

    說明

    若您使用的是極簡模式的控制臺(tái),請單擊控制臺(tái)左上角的2023-01-28_15-57-17.png圖標(biāo),選擇全部功能 > 安全與規(guī)范(DBS) > 數(shù)據(jù)災(zāi)備(DBS) > 災(zāi)備數(shù)據(jù)源

  3. 在上方選擇地域,在云下及他云數(shù)據(jù)庫 > 產(chǎn)品自動(dòng)備份頁簽下,單擊目標(biāo)數(shù)據(jù)源ID進(jìn)入數(shù)據(jù)源詳情頁。

  4. 備份策略頁面中,單擊配置備份策略

  5. 選擇備份計(jì)劃頁面單擊購買備份計(jì)劃,進(jìn)入DBS售賣頁。

  6. 配置如下參數(shù),單擊頁面右下角的立即購買

    配置項(xiàng)

    說明

    商品類型

    請選擇備份實(shí)例(包年包月)

    備份實(shí)例地域

    選擇要存放備份數(shù)據(jù)的地域。

    說明

    請確保備份實(shí)例所在地域與ECS實(shí)例所在地域相同。

    數(shù)據(jù)源類型

    當(dāng)前僅支持MySQL

    規(guī)格

    規(guī)格越高,備份與恢復(fù)的性能越高,支持的規(guī)格為:serverless(僅MySQL邏輯備份支持)、micro(入門型)、small(低配型)、medium(中配型)、large(高配型)、xlarge(高配型-無流量上限)。

    說明
    • 如果數(shù)據(jù)庫實(shí)例(例如生產(chǎn)環(huán)境的數(shù)據(jù)庫)需要高性能的備份實(shí)例快速執(zhí)行備份與恢復(fù)任務(wù),建議選擇xlarge或large規(guī)格,獲取更高的備份恢復(fù)性能。

    • 對備份恢復(fù)性能(速度)要求不高,您可以通過計(jì)算,選擇性價(jià)比最高的備份實(shí)例規(guī)格。更多信息,請參見如何選擇備份實(shí)例規(guī)格

    • 若備份庫表存在表結(jié)構(gòu)不合理、大表、大字段等情況,備份實(shí)例的規(guī)格過小可能會(huì)導(dǎo)致后續(xù)備份實(shí)例資源不足,從而引發(fā)備份異常。因此,建議您在創(chuàng)建時(shí)選擇較高規(guī)格的備份實(shí)例,以免后續(xù)備份出現(xiàn)異常。

    備份方式

    請選擇邏輯備份

    存儲(chǔ)空間

    您創(chuàng)建時(shí)無需選擇容量,后續(xù)根據(jù)實(shí)際存入DBS內(nèi)置存儲(chǔ)中的數(shù)據(jù)量計(jì)費(fèi)。計(jì)費(fèi)詳情,請參見存儲(chǔ)費(fèi)用

    資源組

    配置資源組。選擇默認(rèn)或自定義的資源組,方便備份實(shí)例管理。

    購買數(shù)量

    按需選擇購買數(shù)量,多個(gè)數(shù)據(jù)庫實(shí)例需要?jiǎng)?chuàng)建多個(gè)備份實(shí)例,例如您希望備份數(shù)據(jù)庫實(shí)例A與數(shù)據(jù)庫實(shí)例B,需要購買2個(gè)備份實(shí)例。

    購買時(shí)長

    選擇該備份實(shí)例的購買時(shí)長。

  7. 確認(rèn)訂單頁面,確認(rèn)訂單信息,閱讀并選中服務(wù)協(xié)議,單擊去支付

    支付成功后,請返回步驟5的選擇備份計(jì)劃頁面,單擊已完成支付,即可查看到已創(chuàng)建的備份實(shí)例。

    image

配置備份策略

  1. 選擇備份計(jì)劃頁面選中待配置的備份實(shí)例,并單擊下一步

    image

  2. 選擇庫表頁面,選中需要備份的庫或表,單擊image移動(dòng)到已選擇對象框中,單擊提交

    image..png

  3. 提交成功后,您可以在備份策略頁面的邏輯備份頁簽下,單擊啟動(dòng)按鈕啟動(dòng)備份。

    單擊啟動(dòng)后系統(tǒng)會(huì)立即發(fā)起一次全量和增量備份任務(wù)。

    image

    說明

    如果您期望先完成一些其他操作(例如修改備份策略等),您也可以選擇當(dāng)前暫不啟動(dòng)備份,但后續(xù)系統(tǒng)會(huì)根據(jù)備份策略在備份時(shí)間自動(dòng)啟動(dòng)備份。

用戶自動(dòng)備份

重要
  • 目前僅支持MySQL 5.5版本的數(shù)據(jù)源。

  • 目前僅支持華東1(杭州)地域。

配置備份源以及上傳備份文件

  1. 登錄數(shù)據(jù)管理DMS 5.0
  2. 在頂部菜單欄中,選擇安全與規(guī)范(DBS) > 數(shù)據(jù)災(zāi)備(DBS) > 災(zāi)備數(shù)據(jù)源

    說明

    若您使用的是極簡模式的控制臺(tái),請單擊控制臺(tái)左上角的2023-01-28_15-57-17.png圖標(biāo),選擇全部功能 > 安全與規(guī)范(DBS) > 數(shù)據(jù)災(zāi)備(DBS) > 災(zāi)備數(shù)據(jù)源

  3. 在上方選擇地域,在云下及他云數(shù)據(jù)庫頁簽下,根據(jù)數(shù)據(jù)源類型選擇新增入口。

  4. 單擊新增數(shù)據(jù)源,在彈出的對話框中,配置如下信息,并選中目標(biāo)備份計(jì)劃,單擊頁面右下角下一步

    image

    配置項(xiàng)

    說明

    數(shù)據(jù)源名稱

    建議配置具有業(yè)務(wù)意義的名稱,便于后續(xù)識(shí)別。

    引擎類型

    數(shù)據(jù)庫引擎類型,當(dāng)前僅支持MySQL。

    引擎版本

    選擇數(shù)據(jù)庫引擎的版本。

    引擎參數(shù)

    {"lower_case_table_names":1}

    若沒有可選備份計(jì)劃,單擊購買備份計(jì)劃,進(jìn)入DBS售賣頁,購買備份計(jì)劃。

    說明

    商品類型

    請選擇備份實(shí)例(包年包月),不支持按量付費(fèi)。

    備份實(shí)例地域

    選擇要存放備份數(shù)據(jù)的地域。

    數(shù)據(jù)源類型

    選擇MySQL

    規(guī)格

    選擇xmicro。該規(guī)格提供的免費(fèi)數(shù)據(jù)量額度等,請參見備份計(jì)劃規(guī)格

    備份方式

    選擇物理備份

    存儲(chǔ)空間

    您創(chuàng)建時(shí)無需選擇容量,后續(xù)根據(jù)實(shí)際存入DBS內(nèi)置存儲(chǔ)中的數(shù)據(jù)量計(jì)費(fèi)。計(jì)費(fèi)詳情,請參見存儲(chǔ)費(fèi)用

    資源組

    配置資源組。選擇默認(rèn)或自定義的資源組,方便備份實(shí)例管理。

    購買數(shù)量

    按需選擇購買數(shù)量,多個(gè)數(shù)據(jù)庫實(shí)例需要?jiǎng)?chuàng)建多個(gè)備份實(shí)例,例如您希望備份數(shù)據(jù)庫實(shí)例A與數(shù)據(jù)庫實(shí)例B,需要購買2個(gè)備份實(shí)例。

    購買時(shí)長

    選擇該備份實(shí)例的購買時(shí)長。

  5. 將備份集上傳到指定Bucket中。上傳方法,請參見用戶自動(dòng)備份數(shù)據(jù)上傳指南

  6. 上傳完成后,單擊確定

查看備份信息

用戶自動(dòng)備份頁簽,單擊目標(biāo)數(shù)據(jù)源ID。

image

image

配置備份策略

  1. 用戶自動(dòng)備份頁簽,單擊目標(biāo)數(shù)據(jù)源操作列的查看備份策略

    image

    image

  2. 配置完成之后,單擊確定

看和下載備份數(shù)據(jù)

  1. 用戶自動(dòng)備份頁簽,單擊目標(biāo)數(shù)據(jù)源ID。

  2. 單擊左側(cè)導(dǎo)航欄中的備份數(shù)據(jù)

    說明

    用戶執(zhí)行上傳數(shù)據(jù)腳本并完成數(shù)據(jù)源新建后,當(dāng)用戶新產(chǎn)生一個(gè)備份集數(shù)據(jù),數(shù)據(jù)備份管理系統(tǒng)會(huì)同步這個(gè)備份數(shù)據(jù)到備份數(shù)據(jù)頁面。

    image

  3. 單擊目標(biāo)備份集操作列的下載按鈕獲取下載鏈接,將備份集下載到本地。

    image

創(chuàng)建恢復(fù)任務(wù)

說明

恢復(fù)任務(wù)要求數(shù)據(jù)備份頁面上必須存在已生成的備份集,并且該備份集的狀態(tài)需為完成

  1. 用戶自動(dòng)備份頁簽,單擊目標(biāo)數(shù)據(jù)源ID。

  2. 單擊左側(cè)導(dǎo)航欄中的備份數(shù)據(jù),單擊創(chuàng)建恢復(fù)任務(wù),手動(dòng)配置恢復(fù)參數(shù)。

    image

    參數(shù)名稱

    說明

    恢復(fù)任務(wù)名稱

    請輸入本次恢復(fù)任務(wù)的名稱。建議配置具有業(yè)務(wù)意義的名稱,便于后續(xù)識(shí)別。

    恢復(fù)位置

    選擇恢復(fù)實(shí)例位置,默認(rèn)為恢復(fù)到RDS新實(shí)例。

    數(shù)據(jù)庫所在位置

    選擇數(shù)據(jù)庫所在位置,默認(rèn)為RDS。

    實(shí)例地區(qū)

    選擇實(shí)例所在地區(qū),目前僅支持華東1(杭州)地區(qū)。

    VPC

    選擇創(chuàng)建的專有網(wǎng)絡(luò)。

    VSwitch

    選擇創(chuàng)建的交換機(jī)。

    實(shí)例系列

    選擇恢復(fù)的實(shí)例系列。

    實(shí)例規(guī)格

    選擇恢復(fù)的實(shí)例規(guī)格。

    存儲(chǔ)空間

    選擇所需存儲(chǔ)空間。

    恢復(fù)方式

    選擇恢復(fù)方式,目前僅支持按時(shí)間點(diǎn)恢復(fù)。

    還原時(shí)間

    選擇還原時(shí)間,可選擇恢復(fù)時(shí)間范圍請參考恢復(fù)方式參數(shù)后的數(shù)據(jù)。

  3. 配置完成之后單擊提交,會(huì)生成一個(gè)按所選還原時(shí)間點(diǎn)恢復(fù)的恢復(fù)任務(wù),該任務(wù)信息將以列表的形式展示在恢復(fù)任務(wù)頁面。

查看恢復(fù)任務(wù)

  1. 用戶自動(dòng)備份頁簽,單擊目標(biāo)數(shù)據(jù)源ID。

  2. 單擊左側(cè)導(dǎo)航欄中的任務(wù)管理 > 恢復(fù)任務(wù)

    image

  3. 點(diǎn)擊恢復(fù)結(jié)果列中的實(shí)例ID,可跳轉(zhuǎn)至恢復(fù)的RDS實(shí)例基本信息頁面。

查看恢復(fù)演練

  1. 用戶自動(dòng)備份頁簽,單擊目標(biāo)數(shù)據(jù)源ID。

  2. 單擊左側(cè)導(dǎo)航欄中的恢復(fù)演練

    恢復(fù)演練概覽指標(biāo)

    查看恢復(fù)演練概覽,包含恢復(fù)任務(wù)成功率恢復(fù)時(shí)長均值數(shù)據(jù)備份演練覆蓋率日志備份演練覆蓋率

    image

    名稱

    說明

    恢復(fù)任務(wù)成功率

    在恢復(fù)時(shí)間點(diǎn)在篩選時(shí)間范圍內(nèi)的恢復(fù)任務(wù)成功率。

    恢復(fù)時(shí)長均值

    在篩選時(shí)間范圍內(nèi)恢復(fù)成功任務(wù)的平均耗時(shí)。

    數(shù)據(jù)備份演練覆蓋率

    在篩選時(shí)間范圍內(nèi)數(shù)據(jù)備份在開源MySQL或RDS MySQL上執(zhí)行過恢復(fù)演練的覆蓋率。

    日志備份演練覆蓋率

    在篩選時(shí)間范圍內(nèi)的日志備份在開源MySQL或RDS MySQL上執(zhí)行過恢復(fù)演練的覆蓋率。

    恢復(fù)演練時(shí)間軸

    通過時(shí)間軸展示在篩選時(shí)間范圍內(nèi)的各個(gè)時(shí)間點(diǎn)的恢復(fù)演練詳情,在時(shí)間軸上點(diǎn)擊鼠標(biāo)左鍵可以查看當(dāng)前時(shí)間點(diǎn)的演練信息。

    image

    備份數(shù)據(jù)恢復(fù)演練詳情

    單擊數(shù)據(jù)備份,查看數(shù)據(jù)備份恢復(fù)演練詳情列表。單擊演練結(jié)果列實(shí)例ID,進(jìn)入恢復(fù)的rds 實(shí)例的基本信息頁面。

    image

    單擊日志備份,可以查看日志備份恢復(fù)演練詳情列表。

    image

用戶自動(dòng)備份數(shù)據(jù)上傳指南

準(zhǔn)備工作

環(huán)境依賴

  • 命令工具:Bash、Python3。

  • Python相關(guān):oss2、alibabacloud_openapi_util、alibabacloud_tea_openapi、alibabacloud_tea_util。

## 安裝阿里云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

完整上傳腳本

備份數(shù)據(jù)上傳腳本分為兩部分:

Bash腳本

腳本執(zhí)行處理入口,按需替換實(shí)際執(zhí)行的參數(shù)。

boot_backup.sh:負(fù)責(zé)模擬本地xtrabackup全量備份的流程。

#!/bin/bash
## 阿里云賬號(hào)AccessKey擁有所有API的訪問權(quán)限,風(fēng)險(xiǎn)很高。強(qiáng)烈建議您創(chuàng)建并使用RAM用戶進(jìn)行API訪問或日常運(yùn)維
## 強(qiáng)烈建議不要把 AccessKey 和 AccessKeySecret 保存到代碼里,會(huì)存在密鑰泄漏風(fēng)險(xiǎn),您可以根據(jù)業(yè)務(wù)需要,保存到配置文件里

AK=<ALIBABA_CLOUD_ACCESS_KEY_ID>
SK=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
DBS_API=dbs-api.<您的數(shù)據(jù)源所在地域ID,例如cn-hangzhou>.aliyuncs.com
DATASOURCE_ID=<您的數(shù)據(jù)源ID>

## 獲取腳本當(dāng)前路徑
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

## 執(zhí)行xtrabackup備份命令,將錯(cuò)誤日志輸出的到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

## 獲取當(dāng)前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

## 調(diào)用Python腳本進(jìn)行上傳備份數(shù)據(jù),并注冊備份集元數(shù)據(jù)
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:用于上傳全量和日志備份數(shù)據(jù),解析對應(yīng)的元數(shù)據(jù),并進(jìn)行備份集元數(shù)據(jù)的注冊。

    # -*- 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="Aliyun AccessKeyId.")
        parser.add_argument("--access_key_secret", help="Aliyun AccessKeySecret.")
        parser.add_argument("--endpoint", help="Aliyun API Endpoint.")
        parser.add_argument("--region_code", help="Aliyun DataSource RegionCode.")
        parser.add_argument("--datasource_id", help="Aliyun DataSourceId.")
        parser.add_argument("--data_type", help="BackupSet DataType: FullBackup | LogBackup.")
        parser.add_argument("--file_path", help="BackupSet File Path.")
        parser.add_argument("--xtrabackup_info_path", help="Xtrabackup Info Path.")
        parser.add_argument("--xtrabackup_log_path", help="Xtrabackup Log Path.")
        parser.add_argument("--begin_time", help="Binlog Begin Time.")
        parser.add_argument("--end_time", help="Binlog End Time.")
    
        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()方法得到時(shí)間元組,然后用time.mktime轉(zhuǎn)換為秒級(jí)時(shí)間戳
        timestamp_seconds = time.mktime(dt_obj.timetuple())
        return int(timestamp_seconds) * 1000
    
    
    def create_oss_client(params):
        # 阿里云OSS認(rèn)證信息
        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中的對象鍵,即文件名
        """
        # 設(shè)置分片大小,單位為字節(jié),默認(rèn)1MB
        part_size = 1024 * 1024 * 5
        # 初始化分片上傳
        upload_id = oss_client.init_multipart_upload(object_key).upload_id
    
        # 打開文件并讀取內(nèi)容
        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)
            # Endpoint 請參考 https://api.aliyun.com/product/Rds
            config.endpoint = endpoint
            self.client = OpenApiClient(config)
    
        """
        注冊備份集元數(shù)據(jù)
        """
        def configure_backup_set_info(self, req_param):
            params = open_api_models.Params(
                # 接口名稱,
                action='ConfigureBackupSetInfo',
                # 接口版本,
                version='2021-01-01',
                # 接口協(xié)議,
                protocol='HTTPS',
                # 接口 HTTP 方法,
                method='POST',
                auth_type='AK',
                style='RPC',
                # 接口 PATH,
                pathname='/',
                # 接口請求體內(nèi)容格式,
                req_body_type='json',
                # 接口響應(yīng)體內(nèi)容格式,
                body_type='json'
            )
            # runtime options
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # 返回值為 Map 類型,可從 Map 中獲得三類數(shù)據(jù):響應(yīng)體 body、響應(yīng)頭 headers、HTTP 返回的狀態(tài)碼 statusCode。
            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',
                # 接口協(xié)議,
                protocol='HTTPS',
                # 接口 HTTP 方法,
                method='POST',
                auth_type='AK',
                style='RPC',
                # 接口 PATH,
                pathname='/',
                # 接口請求體內(nèi)容格式,
                req_body_type='json',
                # 接口響應(yīng)體內(nèi)容格式,
                body_type='json'
            )
            # runtime options
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # 返回值為 Map 類型,可從 Map 中獲得三類數(shù)據(jù):響應(yīng)體 body、響應(yīng)頭 headers、HTTP 返回的狀態(tài)碼 statusCode。
            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")
    
            # 上傳數(shù)據(jù)到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")
    
            # 標(biāo)記備份集上傳完成
            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)
    
        # 全量和日志備份分別通過不同方式構(gòu)造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}")
    
        # 上傳數(shù)據(jù),并注冊備份集元信息
        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進(jìn)行元數(shù)據(jù)解析。

    # -*- 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:使用備份產(chǎn)生的日志文件xtrabackup.log進(jìn)行元數(shù)據(jù)解析。

    #!/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):
        """
        根據(jù)給定的日期部分和時(shí)間部分,解析并返回完整的日期時(shí)間字符串。
        """
        # 獲取當(dāng)前年份的前兩位
        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:
                    # 提取日期和時(shí)間部分
                    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. 配置阿里云AccessKeyId和AccessKeySecret、DBS OpenAPI Endpoint,以及對應(yīng)的數(shù)據(jù)源ID。

    #!/bin/bash
    ## 阿里云賬號(hào)AccessKey擁有所有API的訪問權(quán)限,風(fēng)險(xiǎn)很高。強(qiáng)烈建議您創(chuàng)建并使用RAM用戶進(jìn)行API訪問或日常運(yùn)維
    ## 強(qiáng)烈建議不要把 AccessKey 和 AccessKeySecret 保存到代碼里,會(huì)存在密鑰泄漏風(fēng)險(xiǎn),您可以根據(jù)業(yè)務(wù)需要,保存到配置文件里
    
    AK=<ALIBABA_CLOUD_ACCESS_KEY_ID>
    SK=<ALIBABA_CLOUD_ACCESS_KEY_SECRET>
    DBS_API=dbs-api.<您的數(shù)據(jù)源所在地域ID,例如cn-hangzhou>.aliyuncs.com
    DATASOURCE_ID=<您的數(shù)據(jù)源ID>
  2. 執(zhí)行xtrabackup備份命令,將備份數(shù)據(jù)保存到指定的目錄,同時(shí)將錯(cuò)誤日志輸出到xtrabackup.log文件中。

    ## 獲取腳本當(dāng)前路徑
    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
    
    ## 執(zhí)行xtrabackup備份命令,將錯(cuò)誤日志輸出的到xtrabackup.log文件
    ~/innobackupex --defaults-file=/etc/my.cnf --user='<您的數(shù)據(jù)庫賬號(hào),例如root>' --password='<您的數(shù)據(jù)庫密碼,例如root>' --host='<您的數(shù)據(jù)庫IP,例如localhost>' --port=<您的數(shù)據(jù)庫端口號(hào),例如3306> --socket='/var/lib/mysql/mysql.sock' --parallel=4 $XTRA_DATA_DIR/ 2>$XTRA_DATA_DIR/xtrabackup.log
    • 后續(xù)將解析xtrabackup.log文件獲得全量備份集的元數(shù)據(jù)信息:備份開始時(shí)間、備份結(jié)束時(shí)間、一致性時(shí)間點(diǎn)、對應(yīng)Binlog名稱。

    • 限制說明:

      當(dāng)前執(zhí)行xtrabackup備份命令,暫不支持壓縮和加密參數(shù)(--compress --compress-threads和--encrypt --encrypt-key-file --encrypt-threads),使用xtrabackup備份命令時(shí)請先刪除對應(yīng)的參數(shù)。

  3. 將文件目錄形式的全量備份數(shù)據(jù)進(jìn)行g(shù)zip壓縮和打包成tar.gz格式的文件。

    ## 獲取當(dāng)前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
    • 限制說明:當(dāng)前僅支持文件格式的備份數(shù)據(jù)上傳,支持如下格式:

      • tar:目錄文件進(jìn)行tar打包。

      • tar.gz:目錄文件進(jìn)行tar打包,然后進(jìn)行g(shù)zip壓縮。

    • 注意事項(xiàng):

      • 使用tar命令打包前,需要chmod 755命令修改文件目錄權(quán)限。

      • 需進(jìn)入文件夾根目錄,進(jìn)行tar命令的打包和壓縮。

  4. 調(diào)用Python腳本upload_and_register_backup_set.py進(jìn)行備份數(shù)據(jù)的上傳,同時(shí)注冊備份集元數(shù)據(jù)。

    ## 調(diào)用Python腳本進(jìn)行上傳備份數(shù)據(jù),并注冊備份集元數(shù)據(jù)
    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

    參數(shù)

    說明

    --access_key_id

    阿里云AccessKeyId。

    --access_key_secret

    阿里云AccessKeySecret。

    --endpoint

    DBS OpenAPI對應(yīng)的Endpoint。請參見服務(wù)接入點(diǎn)

    --datasource_id

    DBS對應(yīng)的數(shù)據(jù)源ID。

    --region_code

    對應(yīng)地域信息。

    --data_type

    備份數(shù)據(jù)類型,全量備份集:FullBackup,日志備份:LogBackup。

    --file_path

    全量備份數(shù)據(jù)路徑。

    --xtrabackup_log_path

    全量備份xtrabackup命令產(chǎn)生的xtrabackup.log文件路徑。

Python腳本處理流程

  1. main函數(shù)主入口:

    根據(jù)data_type傳參為FullBackug或者LogBackup,分別構(gòu)造元數(shù)據(jù)注冊依賴的extra_meta信息:

    說明
    • BINLOG_FILE:對應(yīng)Binlog名稱。

    • dataBegin:備份開始時(shí)間,毫秒級(jí)別時(shí)間戳。

    • dataEnd:備份結(jié)束時(shí)間,毫秒級(jí)別時(shí)間戳。

    • consistentTime:一致性時(shí)間點(diǎn),秒級(jí)時(shí)間戳。

    • 全量備份extra_meta格式:

      {
        'BINLOG_FILE':'mysql-bin.001',
        'version':'5.5',
        'dataBegin':17274********,
        'dataEnd':17274********,
        'consistentTime':17274********
      }
    • 日志備份extra_meta格式:

      {
        'dataBegin':17274********,
        'dataEnd':17274********
      }
  2. 調(diào)用OssUploader.upload_and_register_backup_set方法進(jìn)行備份數(shù)據(jù)上傳和元數(shù)據(jù)注冊。

    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)
    
        # 全量和日志備份分別通過不同方式構(gòu)造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}")
    
        # 上傳數(shù)據(jù),并注冊備份集元信息
        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方法備份數(shù)據(jù)上傳流程。

    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)
            # Endpoint 請參考 https://api.aliyun.com/product/Rds
            config.endpoint = endpoint
            self.client = OpenApiClient(config)
    
        """
        注冊備份集元數(shù)據(jù)
        """
        def configure_backup_set_info(self, req_param):
            params = open_api_models.Params(
                # 接口名稱,
                action='ConfigureBackupSetInfo',
                # 接口版本,
                version='2021-01-01',
                # 接口協(xié)議,
                protocol='HTTPS',
                # 接口 HTTP 方法,
                method='POST',
                auth_type='AK',
                style='RPC',
                # 接口 PATH,
                pathname='/',
                # 接口請求體內(nèi)容格式,
                req_body_type='json',
                # 接口響應(yīng)體內(nèi)容格式,
                body_type='json'
            )
            # runtime options
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # 返回值為 Map 類型,可從 Map 中獲得三類數(shù)據(jù):響應(yīng)體 body、響應(yīng)頭 headers、HTTP 返回的狀態(tài)碼 statusCode。
            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',
                # 接口協(xié)議,
                protocol='HTTPS',
                # 接口 HTTP 方法,
                method='POST',
                auth_type='AK',
                style='RPC',
                # 接口 PATH,
                pathname='/',
                # 接口請求體內(nèi)容格式,
                req_body_type='json',
                # 接口響應(yīng)體內(nèi)容格式,
                body_type='json'
            )
            # runtime options
            runtime = util_models.RuntimeOptions()
            request = open_api_models.OpenApiRequest(
                query=OpenApiUtilClient.query(req_param)
            )
            # 返回值為 Map 類型,可從 Map 中獲得三類數(shù)據(jù):響應(yīng)體 body、響應(yīng)頭 headers、HTTP 返回的狀態(tài)碼 statusCode。
            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")
    
            # 上傳數(shù)據(jù)到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")
    
            # 標(biāo)記備份集上傳完成
            params['UploadStatus'] = 'UploadSuccess'
            self.configure_backup_set_info(params)
            print(f"------ configure_backup_set_info success: {file_path}, {data_type}, {params['BackupSetId']}, UploadSuccess\n")