7.1 备份策略与类型

7.1.1 备份基础概念

class MySQLBackupStrategy:
    def __init__(self):
        self.backup_types = {
            "按数据内容分类": {
                "完全备份": {
                    "定义": "备份整个数据库的所有数据",
                    "优点": ["恢复简单", "数据完整", "独立性强"],
                    "缺点": ["备份时间长", "存储空间大", "网络传输慢"],
                    "适用场景": "数据量小,变化不频繁的系统"
                },
                "增量备份": {
                    "定义": "只备份自上次备份以来发生变化的数据",
                    "优点": ["备份速度快", "存储空间小", "网络传输快"],
                    "缺点": ["恢复复杂", "依赖性强", "备份链风险"],
                    "适用场景": "数据量大,变化频繁的系统"
                },
                "差异备份": {
                    "定义": "备份自上次完全备份以来发生变化的数据",
                    "优点": ["恢复相对简单", "存储适中", "备份链短"],
                    "缺点": ["备份时间逐渐增长", "存储空间逐渐增大"],
                    "适用场景": "平衡备份效率和恢复复杂度的系统"
                }
            },
            "按备份方式分类": {
                "逻辑备份": {
                    "定义": "备份数据库的逻辑结构和数据内容",
                    "工具": ["mysqldump", "mysqlpump", "mydumper"],
                    "优点": ["可读性好", "跨平台", "灵活性高", "可选择性备份"],
                    "缺点": ["备份恢复慢", "占用CPU高", "不包含日志"],
                    "格式": "SQL语句文件"
                },
                "物理备份": {
                    "定义": "直接备份数据库文件和日志文件",
                    "工具": ["MySQL Enterprise Backup", "Percona XtraBackup", "文件系统快照"],
                    "优点": ["备份恢复快", "包含所有文件", "支持增量"],
                    "缺点": ["平台依赖", "灵活性差", "需要停机或特殊工具"],
                    "格式": "二进制文件"
                }
            },
            "按服务状态分类": {
                "热备份": {
                    "定义": "数据库正常运行时进行备份",
                    "特点": ["不影响业务", "可能数据不一致", "需要特殊工具"],
                    "适用引擎": "InnoDB(支持事务)"
                },
                "温备份": {
                    "定义": "数据库只读状态下进行备份",
                    "特点": ["数据一致", "影响写操作", "读操作正常"],
                    "实现方式": "FLUSH TABLES WITH READ LOCK"
                },
                "冷备份": {
                    "定义": "数据库停止服务时进行备份",
                    "特点": ["数据完全一致", "完全停机", "备份最可靠"],
                    "适用场景": "维护窗口期间"
                }
            }
        }
        
        self.backup_strategies = {
            "3-2-1策略": {
                "原则": "3份副本,2种介质,1份异地",
                "说明": {
                    "3份副本": "生产数据 + 2份备份",
                    "2种介质": "本地磁盘 + 云存储/磁带",
                    "1份异地": "至少1份备份存储在异地"
                },
                "优势": "最大化数据安全性"
            },
            "GFS策略": {
                "原则": "Grandfather-Father-Son(祖父-父亲-儿子)",
                "说明": {
                    "Son(日备份)": "每日增量备份,保留1周",
                    "Father(周备份)": "每周完全备份,保留1月",
                    "Grandfather(月备份)": "每月完全备份,保留1年"
                },
                "优势": "平衡存储成本和恢复需求"
            },
            "Tower of Hanoi策略": {
                "原则": "基于汉诺塔算法的备份轮换",
                "说明": "使用数学算法优化备份介质使用",
                "优势": "最小化备份介质数量"
            }
        }
    
    def explain_backup_types(self):
        """解释备份类型"""
        print("MySQL备份类型详解:")
        print("=" * 60)
        
        for category, types in self.backup_types.items():
            print(f"\n{category}:")
            for backup_type, details in types.items():
                print(f"\n  {backup_type}:")
                for key, value in details.items():
                    if isinstance(value, list):
                        print(f"    {key}: {', '.join(value)}")
                    else:
                        print(f"    {key}: {value}")
    
    def explain_backup_strategies(self):
        """解释备份策略"""
        print("\n备份策略详解:")
        print("=" * 40)
        
        for strategy, details in self.backup_strategies.items():
            print(f"\n{strategy}:")
            print(f"  原则: {details['原则']}")
            if '说明' in details:
                print("  说明:")
                for key, value in details['说明'].items():
                    print(f"    {key}: {value}")
            print(f"  优势: {details['优势']}")
    
    def backup_planning_guide(self):
        """备份规划指南"""
        guide = """
备份规划指南:

## 1. 需求分析

### 业务需求评估:
- RTO(恢复时间目标):系统能容忍的最大停机时间
- RPO(恢复点目标):系统能容忍的最大数据丢失量
- 数据重要性等级:核心业务数据 vs 一般业务数据
- 合规性要求:法律法规对数据保留的要求

### 技术环境评估:
- 数据库大小:影响备份时间和存储需求
- 数据变化频率:影响备份频率和策略选择
- 网络带宽:影响备份传输和异地备份
- 存储容量:影响备份保留策略
- 硬件性能:影响备份和恢复速度

## 2. 备份策略设计

### 小型数据库(< 10GB):
- 策略:每日完全备份 + 二进制日志备份
- 工具:mysqldump + mysqlbinlog
- 保留:本地7天,异地30天
- 恢复时间:< 1小时

### 中型数据库(10GB - 100GB):
- 策略:周完全备份 + 日增量备份 + 二进制日志备份
- 工具:Percona XtraBackup + mysqlbinlog
- 保留:本地30天,异地90天
- 恢复时间:< 4小时

### 大型数据库(> 100GB):
- 策略:月完全备份 + 周差异备份 + 日增量备份 + 实时日志备份
- 工具:Percona XtraBackup + 自动化脚本
- 保留:本地90天,异地1年
- 恢复时间:< 8小时

## 3. 备份时间规划

### 备份窗口选择:
- 业务低峰期:减少对生产系统的影响
- 避开批处理时间:防止资源竞争
- 考虑时区差异:多地域部署的系统
- 预留缓冲时间:处理备份失败的情况

### 备份频率建议:
- 完全备份:每周1次(小型系统可每日)
- 增量备份:每日1次
- 二进制日志备份:每小时或实时
- 配置文件备份:每次变更后

## 4. 存储规划

### 本地存储:
- 快速恢复:SSD存储,提高恢复速度
- 容量规划:至少3倍数据库大小
- 冗余保护:RAID配置,防止硬件故障
- 定期清理:自动删除过期备份

### 异地存储:
- 云存储:AWS S3、阿里云OSS、腾讯云COS
- 传统备份:磁带库、异地机房
- 加密传输:保护数据传输安全
- 访问控制:限制备份文件访问权限

## 5. 监控和告警

### 备份监控指标:
- 备份成功率:监控备份任务执行状态
- 备份时间:监控备份耗时趋势
- 备份大小:监控备份文件大小变化
- 存储使用率:监控备份存储空间

### 告警设置:
- 备份失败:立即告警
- 备份超时:超过预期时间告警
- 存储不足:存储使用率超过80%告警
- 文件损坏:备份文件校验失败告警

## 6. 测试和验证

### 备份有效性测试:
- 定期恢复测试:每月至少1次
- 完整性校验:备份文件MD5检查
- 恢复时间测试:验证RTO目标
- 数据一致性测试:验证恢复数据正确性

### 灾难恢复演练:
- 季度演练:模拟真实灾难场景
- 文档更新:根据演练结果更新流程
- 人员培训:确保团队熟悉恢复流程
- 流程优化:持续改进备份恢复流程

## 7. 成本优化

### 存储成本优化:
- 压缩备份:减少存储空间需求
- 分层存储:热数据SSD,冷数据HDD
- 生命周期管理:自动转移到低成本存储
- 重复数据删除:减少重复数据存储

### 网络成本优化:
- 增量传输:只传输变化的数据
- 压缩传输:减少网络带宽使用
- 传输时间优化:选择网络空闲时段
- CDN加速:提高异地传输速度
"""
        
        print("\n备份规划指南:")
        print("=" * 40)
        print(guide)

# 备份策略演示
backup_demo = MySQLBackupStrategy()
backup_demo.explain_backup_types()
backup_demo.explain_backup_strategies()
backup_demo.backup_planning_guide()

7.1.2 备份工具对比

class MySQLBackupTools:
    def __init__(self):
        self.tools_comparison = {
            "mysqldump": {
                "类型": "逻辑备份工具",
                "开发者": "MySQL官方",
                "支持版本": "所有MySQL版本",
                "备份格式": "SQL文本文件",
                "优点": [
                    "官方工具,稳定可靠",
                    "跨平台兼容性好",
                    "可选择性备份(库、表、行)",
                    "支持数据转换和过滤",
                    "备份文件可读性强"
                ],
                "缺点": [
                    "备份速度慢",
                    "恢复速度慢",
                    "占用大量CPU和内存",
                    "不支持增量备份",
                    "大数据库备份困难"
                ],
                "适用场景": "小到中型数据库,需要灵活性的场景",
                "最大数据量": "< 100GB"
            },
            "mysqlpump": {
                "类型": "逻辑备份工具",
                "开发者": "MySQL官方",
                "支持版本": "MySQL 5.7+",
                "备份格式": "SQL文本文件",
                "优点": [
                    "支持并行备份",
                    "备份速度比mysqldump快",
                    "支持压缩",
                    "支持进度显示",
                    "更好的性能"
                ],
                "缺点": [
                    "版本要求高",
                    "功能相对简单",
                    "社区使用较少",
                    "文档相对较少"
                ],
                "适用场景": "MySQL 5.7+环境,需要并行备份",
                "最大数据量": "< 500GB"
            },
            "mydumper": {
                "类型": "逻辑备份工具",
                "开发者": "第三方开源",
                "支持版本": "MySQL 5.0+",
                "备份格式": "多个SQL文件",
                "优点": [
                    "多线程并行备份",
                    "备份速度快",
                    "支持一致性快照",
                    "支持压缩",
                    "可恢复到指定时间点"
                ],
                "缺点": [
                    "需要额外安装",
                    "配置相对复杂",
                    "依赖第三方维护"
                ],
                "适用场景": "大型数据库逻辑备份",
                "最大数据量": "< 1TB"
            },
            "Percona XtraBackup": {
                "类型": "物理备份工具",
                "开发者": "Percona",
                "支持版本": "MySQL 5.1+, Percona Server, MariaDB",
                "备份格式": "二进制文件",
                "优点": [
                    "热备份,不锁表",
                    "支持增量备份",
                    "备份和恢复速度快",
                    "支持压缩和加密",
                    "支持流式备份"
                ],
                "缺点": [
                    "只支持InnoDB和XtraDB",
                    "平台依赖性强",
                    "配置相对复杂",
                    "需要额外安装"
                ],
                "适用场景": "大型生产环境,InnoDB引擎",
                "最大数据量": "无限制"
            },
            "MySQL Enterprise Backup": {
                "类型": "物理备份工具",
                "开发者": "MySQL官方",
                "支持版本": "MySQL 5.5+",
                "备份格式": "二进制文件",
                "优点": [
                    "官方工具",
                    "热备份",
                    "支持增量备份",
                    "支持压缩和加密",
                    "集成度高"
                ],
                "缺点": [
                    "商业版本,需要许可证",
                    "成本较高",
                    "功能相对有限"
                ],
                "适用场景": "企业级环境,有预算支持",
                "最大数据量": "无限制"
            },
            "文件系统快照": {
                "类型": "物理备份方法",
                "开发者": "操作系统/存储厂商",
                "支持版本": "所有版本",
                "备份格式": "文件系统镜像",
                "优点": [
                    "备份速度极快",
                    "几乎瞬时完成",
                    "存储效率高",
                    "支持快速恢复"
                ],
                "缺点": [
                    "需要特殊存储系统",
                    "可能数据不一致",
                    "平台依赖性强",
                    "成本较高"
                ],
                "适用场景": "企业级存储环境",
                "最大数据量": "无限制"
            }
        }
        
        self.selection_criteria = {
            "数据库大小": {
                "< 10GB": "mysqldump",
                "10GB - 100GB": "mysqldump 或 mydumper",
                "100GB - 1TB": "mydumper 或 XtraBackup",
                "> 1TB": "XtraBackup 或 Enterprise Backup"
            },
            "备份时间要求": {
                "不敏感": "mysqldump",
                "中等敏感": "mydumper 或 mysqlpump",
                "高度敏感": "XtraBackup 或 快照"
            },
            "恢复时间要求": {
                "不敏感": "逻辑备份工具",
                "中等敏感": "物理备份工具",
                "高度敏感": "快照 + 二进制日志"
            },
            "预算考虑": {
                "低预算": "开源工具(mysqldump, mydumper, XtraBackup)",
                "中等预算": "开源工具 + 云存储",
                "高预算": "商业工具 + 企业级存储"
            }
        }
    
    def compare_tools(self):
        """对比备份工具"""
        print("MySQL备份工具对比:")
        print("=" * 80)
        
        for tool, details in self.tools_comparison.items():
            print(f"\n{tool}:")
            print(f"  类型: {details['类型']}")
            print(f"  开发者: {details['开发者']}")
            print(f"  支持版本: {details['支持版本']}")
            print(f"  备份格式: {details['备份格式']}")
            print(f"  优点: {', '.join(details['优点'])}")
            print(f"  缺点: {', '.join(details['缺点'])}")
            print(f"  适用场景: {details['适用场景']}")
            print(f"  最大数据量: {details['最大数据量']}")
    
    def selection_guide(self):
        """工具选择指南"""
        print("\n备份工具选择指南:")
        print("=" * 50)
        
        for criterion, options in self.selection_criteria.items():
            print(f"\n{criterion}:")
            for condition, recommendation in options.items():
                print(f"  {condition}: {recommendation}")
    
    def performance_comparison(self):
        """性能对比"""
        comparison = """
备份工具性能对比(基于100GB数据库测试):

## 1. 备份速度对比

工具                    备份时间    CPU使用率   内存使用    并发支持
mysqldump              4-6小时     60-80%      2-4GB      单线程
mysqlpump              2-3小时     40-60%      1-2GB      多线程
mydumper               1-2小时     30-50%      1-2GB      多线程
XtraBackup             30-60分钟   20-40%      500MB-1GB  单线程
Enterprise Backup      30-60分钟   20-40%      500MB-1GB  单线程
文件系统快照           1-5分钟     5-10%       100MB      N/A

## 2. 恢复速度对比

工具                    恢复时间    资源占用    一致性检查
mysqldump              6-8小时     高          自动
mysqlpump              4-6小时     高          自动
mydumper               3-5小时     中等        自动
XtraBackup             1-2小时     低          需要prepare
Enterprise Backup      1-2小时     低          需要prepare
文件系统快照           5-15分钟    极低        需要额外检查

## 3. 存储空间对比

工具                    压缩比      存储效率    传输效率
mysqldump              60-80%      中等        中等
mysqlpump              60-80%      中等        中等
mydumper               60-80%      中等        中等
XtraBackup             70-90%      高          高
Enterprise Backup      70-90%      高          高
文件系统快照           90-95%      极高        极高

## 4. 功能特性对比

功能                    mysqldump   mydumper    XtraBackup  快照
增量备份               ❌          ❌          ✅          ✅
热备份                 ❌          ✅          ✅          ⚠️
并行备份               ❌          ✅          ❌          N/A
压缩支持               ✅          ✅          ✅          ✅
加密支持               ❌          ❌          ✅          ⚠️
跨平台                 ✅          ✅          ⚠️          ❌
选择性备份             ✅          ✅          ❌          ❌
时间点恢复             ✅          ✅          ✅          ✅

注释:
✅ = 完全支持
⚠️ = 部分支持或需要额外配置
❌ = 不支持
N/A = 不适用

## 5. 选择建议

### 小型数据库(< 10GB):
推荐:mysqldump
理由:简单可靠,功能完整,性能影响可接受

### 中型数据库(10GB - 100GB):
推荐:mydumper(逻辑备份)或 XtraBackup(物理备份)
理由:平衡性能和功能,支持并行处理

### 大型数据库(> 100GB):
推荐:XtraBackup + 增量备份
理由:性能优异,支持热备份和增量备份

### 企业级环境:
推荐:Enterprise Backup 或 存储快照
理由:企业级支持,完整的备份解决方案

### 云环境:
推荐:XtraBackup + 云存储
理由:成本效益好,扩展性强,集成度高
"""
        
        print("\n性能对比:")
        print("=" * 40)
        print(comparison)

# 备份工具演示
tools_demo = MySQLBackupTools()
tools_demo.compare_tools()
tools_demo.selection_guide()
tools_demo.performance_comparison()

7.2 逻辑备份实践

7.2.1 mysqldump详解

class MySQLDumpPractice:
    def __init__(self):
        self.common_options = {
            "基础选项": {
                "--host, -h": "指定MySQL服务器主机名或IP地址",
                "--port, -P": "指定MySQL服务器端口号",
                "--user, -u": "指定连接用户名",
                "--password, -p": "指定连接密码",
                "--databases": "指定要备份的数据库名称",
                "--all-databases": "备份所有数据库",
                "--tables": "指定要备份的表名称"
            },
            "输出控制": {
                "--result-file": "指定输出文件名",
                "--tab": "生成制表符分隔的文本文件",
                "--xml": "生成XML格式输出",
                "--complete-insert": "生成完整的INSERT语句",
                "--extended-insert": "使用多行INSERT语法(默认)",
                "--no-create-info, -t": "不包含CREATE TABLE语句",
                "--no-data, -d": "只备份表结构,不备份数据"
            },
            "性能优化": {
                "--single-transaction": "在单个事务中备份(InnoDB推荐)",
                "--lock-tables": "备份前锁定所有表",
                "--lock-all-tables": "备份前锁定所有数据库的所有表",
                "--quick, -q": "快速备份,逐行检索结果",
                "--opt": "启用优化选项(默认)",
                "--skip-opt": "禁用优化选项"
            },
            "数据过滤": {
                "--where": "指定WHERE条件过滤数据",
                "--ignore-table": "忽略指定的表",
                "--no-create-db": "不包含CREATE DATABASE语句",
                "--add-drop-database": "在CREATE DATABASE前添加DROP DATABASE",
                "--add-drop-table": "在CREATE TABLE前添加DROP TABLE"
            },
            "字符集和编码": {
                "--default-character-set": "指定字符集",
                "--hex-blob": "使用十六进制格式备份BLOB数据",
                "--skip-set-charset": "不在输出中设置字符集"
            },
            "复制相关": {
                "--master-data": "包含二进制日志信息(用于复制)",
                "--dump-slave": "从从服务器备份时包含主服务器信息",
                "--apply-slave-statements": "包含STOP/START SLAVE语句",
                "--include-master-host-port": "包含主服务器主机和端口信息"
            }
        }
        
        self.backup_scenarios = {
            "完整数据库备份": {
                "命令": "mysqldump -u root -p --single-transaction --routines --triggers --all-databases > full_backup.sql",
                "说明": "备份所有数据库,包括存储过程和触发器",
                "适用场景": "完整系统备份"
            },
            "单个数据库备份": {
                "命令": "mysqldump -u root -p --single-transaction --routines --triggers myapp > myapp_backup.sql",
                "说明": "备份指定数据库",
                "适用场景": "单应用备份"
            },
            "多个数据库备份": {
                "命令": "mysqldump -u root -p --single-transaction --databases myapp1 myapp2 myapp3 > multi_backup.sql",
                "说明": "备份多个指定数据库",
                "适用场景": "相关应用备份"
            },
            "表结构备份": {
                "命令": "mysqldump -u root -p --no-data --routines --triggers myapp > myapp_schema.sql",
                "说明": "只备份表结构和存储过程",
                "适用场景": "开发环境同步"
            },
            "数据备份": {
                "命令": "mysqldump -u root -p --no-create-info --skip-triggers myapp > myapp_data.sql",
                "说明": "只备份数据,不包含表结构",
                "适用场景": "数据迁移"
            },
            "条件备份": {
                "命令": "mysqldump -u root -p --single-transaction --where='created_at >= \"2024-01-01\"' myapp users > users_2024.sql",
                "说明": "根据条件备份部分数据",
                "适用场景": "数据分析和测试"
            },
            "压缩备份": {
                "命令": "mysqldump -u root -p --single-transaction --all-databases | gzip > backup_$(date +%Y%m%d).sql.gz",
                "说明": "备份并压缩",
                "适用场景": "节省存储空间"
            },
            "远程备份": {
                "命令": "mysqldump -h 192.168.1.100 -u backup_user -p --single-transaction myapp | ssh backup_server 'cat > /backup/myapp_$(date +%Y%m%d).sql'",
                "说明": "备份到远程服务器",
                "适用场景": "异地备份"
            }
        }
    
    def explain_options(self):
        """解释mysqldump选项"""
        print("mysqldump选项详解:")
        print("=" * 60)
        
        for category, options in self.common_options.items():
            print(f"\n{category}:")
            for option, description in options.items():
                print(f"  {option}: {description}")
    
    def show_backup_scenarios(self):
        """显示备份场景"""
        print("\n常用备份场景:")
        print("=" * 40)
        
        for scenario, details in self.backup_scenarios.items():
            print(f"\n{scenario}:")
            print(f"  命令: {details['命令']}")
            print(f"  说明: {details['说明']}")
            print(f"  适用场景: {details['适用场景']}")
    
    def advanced_examples(self):
        """高级使用示例"""
        examples = """
高级使用示例:

## 1. 自动化备份脚本

#!/bin/bash
# MySQL自动备份脚本

# 配置变量
DB_USER="backup_user"
DB_PASS="backup_password"
DB_HOST="localhost"
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="$BACKUP_DIR/backup.log"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 记录开始时间
echo "$(date): Starting backup" >> $LOG_FILE

# 执行备份
mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASS \
    --single-transaction \
    --routines \
    --triggers \
    --all-databases \
    --master-data=2 \
    --flush-logs \
    --delete-master-logs | \
    gzip > $BACKUP_DIR/full_backup_$DATE.sql.gz

# 检查备份结果
if [ $? -eq 0 ]; then
    echo "$(date): Backup completed successfully" >> $LOG_FILE
    
    # 验证备份文件
    if [ -f "$BACKUP_DIR/full_backup_$DATE.sql.gz" ]; then
        SIZE=$(du -h "$BACKUP_DIR/full_backup_$DATE.sql.gz" | cut -f1)
        echo "$(date): Backup file size: $SIZE" >> $LOG_FILE
        
        # 测试备份文件完整性
        gunzip -t "$BACKUP_DIR/full_backup_$DATE.sql.gz"
        if [ $? -eq 0 ]; then
            echo "$(date): Backup file integrity verified" >> $LOG_FILE
        else
            echo "$(date): ERROR: Backup file corrupted" >> $LOG_FILE
            exit 1
        fi
    else
        echo "$(date): ERROR: Backup file not found" >> $LOG_FILE
        exit 1
    fi
else
    echo "$(date): ERROR: Backup failed" >> $LOG_FILE
    exit 1
fi

# 清理旧备份(保留7天)
find $BACKUP_DIR -name "full_backup_*.sql.gz" -mtime +7 -delete
echo "$(date): Old backups cleaned up" >> $LOG_FILE

# 上传到云存储(可选)
# aws s3 cp $BACKUP_DIR/full_backup_$DATE.sql.gz s3://my-backup-bucket/mysql/

echo "$(date): Backup process completed" >> $LOG_FILE

## 2. 分库备份脚本

#!/bin/bash
# 分库备份脚本

DB_USER="backup_user"
DB_PASS="backup_password"
DB_HOST="localhost"
BACKUP_DIR="/backup/mysql/databases"
DATE=$(date +%Y%m%d)

# 获取所有数据库列表
DATABASES=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW DATABASES;" | grep -Ev "^(Database|information_schema|performance_schema|mysql|sys)$")

# 为每个数据库创建备份
for DB in $DATABASES; do
    echo "Backing up database: $DB"
    
    # 创建数据库专用目录
    mkdir -p $BACKUP_DIR/$DB
    
    # 备份数据库
    mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASS \
        --single-transaction \
        --routines \
        --triggers \
        --events \
        --databases $DB | \
        gzip > $BACKUP_DIR/$DB/${DB}_$DATE.sql.gz
    
    if [ $? -eq 0 ]; then
        echo "Database $DB backed up successfully"
    else
        echo "ERROR: Failed to backup database $DB"
    fi
done

## 3. 表级备份脚本

#!/bin/bash
# 表级备份脚本

DB_USER="backup_user"
DB_PASS="backup_password"
DB_HOST="localhost"
DB_NAME="myapp"
BACKUP_DIR="/backup/mysql/tables"
DATE=$(date +%Y%m%d)

# 获取所有表列表
TABLES=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $DB_NAME -e "SHOW TABLES;" | grep -v "Tables_in_")

# 为每个表创建备份
for TABLE in $TABLES; do
    echo "Backing up table: $TABLE"
    
    # 创建表专用目录
    mkdir -p $BACKUP_DIR/$DB_NAME
    
    # 备份表结构
    mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASS \
        --no-data \
        $DB_NAME $TABLE > $BACKUP_DIR/$DB_NAME/${TABLE}_schema_$DATE.sql
    
    # 备份表数据
    mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASS \
        --no-create-info \
        --single-transaction \
        $DB_NAME $TABLE | \
        gzip > $BACKUP_DIR/$DB_NAME/${TABLE}_data_$DATE.sql.gz
    
    if [ $? -eq 0 ]; then
        echo "Table $TABLE backed up successfully"
    else
        echo "ERROR: Failed to backup table $TABLE"
    fi
done

## 4. 增量备份脚本(基于二进制日志)

#!/bin/bash
# 二进制日志增量备份脚本

DB_USER="backup_user"
DB_PASS="backup_password"
DB_HOST="localhost"
BACKUP_DIR="/backup/mysql/binlog"
DATE=$(date +%Y%m%d)
LAST_BACKUP_FILE="$BACKUP_DIR/last_backup_position.txt"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 获取当前二进制日志位置
CURRENT_LOG=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW MASTER STATUS\G" | grep "File:" | awk '{print $2}')
CURRENT_POS=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW MASTER STATUS\G" | grep "Position:" | awk '{print $2}')

# 读取上次备份位置
if [ -f "$LAST_BACKUP_FILE" ]; then
    LAST_LOG=$(grep "File:" $LAST_BACKUP_FILE | awk '{print $2}')
    LAST_POS=$(grep "Position:" $LAST_BACKUP_FILE | awk '{print $2}')
else
    LAST_LOG=$CURRENT_LOG
    LAST_POS=4
fi

# 备份二进制日志
if [ "$LAST_LOG" = "$CURRENT_LOG" ]; then
    # 同一个日志文件,备份指定位置范围
    mysqlbinlog --start-position=$LAST_POS --stop-position=$CURRENT_POS \
        /var/lib/mysql/$CURRENT_LOG > $BACKUP_DIR/incremental_$DATE.sql
else
    # 跨多个日志文件,需要分别处理
    mysqlbinlog --start-position=$LAST_POS /var/lib/mysql/$LAST_LOG > $BACKUP_DIR/incremental_$DATE.sql
    
    # 获取中间的日志文件
    LOGS=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "SHOW BINARY LOGS;" | awk '{print $1}' | grep -v "Log_name")
    
    for LOG in $LOGS; do
        if [[ "$LOG" > "$LAST_LOG" && "$LOG" < "$CURRENT_LOG" ]]; then
            mysqlbinlog /var/lib/mysql/$LOG >> $BACKUP_DIR/incremental_$DATE.sql
        fi
    done
    
    # 最后一个日志文件
    mysqlbinlog --stop-position=$CURRENT_POS /var/lib/mysql/$CURRENT_LOG >> $BACKUP_DIR/incremental_$DATE.sql
fi

# 压缩增量备份
gzip $BACKUP_DIR/incremental_$DATE.sql

# 更新备份位置记录
echo "File: $CURRENT_LOG" > $LAST_BACKUP_FILE
echo "Position: $CURRENT_POS" >> $LAST_BACKUP_FILE
echo "Date: $(date)" >> $LAST_BACKUP_FILE

echo "Incremental backup completed: incremental_$DATE.sql.gz"

## 5. 定时任务配置

# 编辑crontab
crontab -e

# 添加以下任务
# 每日凌晨2点执行完全备份
0 2 * * * /backup/scripts/full_backup.sh

# 每4小时执行增量备份
0 */4 * * * /backup/scripts/incremental_backup.sh

# 每周日凌晨1点清理旧备份
0 1 * * 0 /backup/scripts/cleanup_old_backups.sh

# 每月1号凌晨3点执行备份验证
0 3 1 * * /backup/scripts/verify_backups.sh
"""
        
        print("\n高级使用示例:")
        print("=" * 40)
        print(examples)

# mysqldump实践演示
mysqldump_demo = MySQLDumpPractice()
mysqldump_demo.explain_options()
mysqldump_demo.show_backup_scenarios()
mysqldump_demo.advanced_examples()

7.2.2 mydumper并行备份

class MyDumperPractice:
    def __init__(self):
        self.mydumper_options = {
            "连接选项": {
                "-h, --host": "MySQL服务器主机名",
                "-u, --user": "连接用户名",
                "-p, --password": "连接密码",
                "-P, --port": "MySQL服务器端口",
                "-S, --socket": "Unix套接字文件路径"
            },
            "备份控制": {
                "-B, --database": "指定要备份的数据库",
                "-T, --tables-list": "指定要备份的表列表",
                "--regex": "使用正则表达式匹配表名",
                "-o, --outputdir": "输出目录",
                "-c, --compress": "压缩输出文件",
                "-e, --build-empty-files": "为空表创建文件"
            },
            "性能选项": {
                "-t, --threads": "并行线程数(默认4)",
                "-r, --rows": "每个文件的行数限制",
                "-F, --chunk-filesize": "每个文件的大小限制(MB)",
                "--single-transaction": "使用单个事务(InnoDB推荐)",
                "--trx-consistency-only": "只对事务表使用一致性"
            },
            "过滤选项": {
                "--where": "WHERE条件过滤",
                "--no-schemas": "不备份表结构",
                "--no-data": "不备份数据",
                "--triggers": "备份触发器",
                "--events": "备份事件",
                "--routines": "备份存储过程和函数"
            },
            "日志选项": {
                "-v, --verbose": "详细输出",
                "-L, --logfile": "日志文件路径",
                "--less-locking": "减少锁定时间"
            }
        }
        
        self.myloader_options = {
            "连接选项": {
                "-h, --host": "MySQL服务器主机名",
                "-u, --user": "连接用户名",
                "-p, --password": "连接密码",
                "-P, --port": "MySQL服务器端口",
                "-S, --socket": "Unix套接字文件路径"
            },
            "恢复控制": {
                "-d, --directory": "备份文件目录",
                "-B, --database": "目标数据库名",
                "-s, --source-db": "源数据库名",
                "-o, --overwrite-tables": "覆盖已存在的表",
                "-e, --enable-binlog": "启用二进制日志"
            },
            "性能选项": {
                "-t, --threads": "并行线程数",
                "--rows": "每次插入的行数",
                "--compress-protocol": "使用压缩协议"
            },
            "安全选项": {
                "--skip-triggers": "跳过触发器",
                "--skip-post": "跳过POST SQL",
                "--no-locks": "不使用锁"
            }
        }
    
    def explain_mydumper_options(self):
        """解释mydumper选项"""
        print("mydumper选项详解:")
        print("=" * 60)
        
        for category, options in self.mydumper_options.items():
            print(f"\n{category}:")
            for option, description in options.items():
                print(f"  {option}: {description}")
    
    def explain_myloader_options(self):
        """解释myloader选项"""
        print("\nmyloader选项详解:")
        print("=" * 60)
        
        for category, options in self.myloader_options.items():
            print(f"\n{category}:")
            for option, description in options.items():
                print(f"  {option}: {description}")
    
    def mydumper_examples(self):
        """mydumper使用示例"""
        examples = """
mydumper使用示例:

## 1. 基础备份命令

# 备份所有数据库
mydumper -u root -p password -c -o /backup/all_databases/

# 备份指定数据库
mydumper -u root -p password -B myapp -c -o /backup/myapp/

# 备份多个数据库
mydumper -u root -p password -B "myapp1,myapp2,myapp3" -c -o /backup/multi_db/

# 备份指定表
mydumper -u root -p password -B myapp -T "users,orders,products" -c -o /backup/tables/

## 2. 性能优化备份

# 使用8个并行线程
mydumper -u root -p password -t 8 -c -o /backup/parallel/

# 限制每个文件大小为100MB
mydumper -u root -p password -F 100 -c -o /backup/chunked/

# 限制每个文件最多10万行
mydumper -u root -p password -r 100000 -c -o /backup/rows_limited/

# 单事务备份(InnoDB推荐)
mydumper -u root -p password --single-transaction -c -o /backup/consistent/

## 3. 条件备份

# 使用WHERE条件
mydumper -u root -p password -B myapp -T users --where="created_at >= '2024-01-01'" -c -o /backup/conditional/

# 使用正则表达式匹配表名
mydumper -u root -p password -B myapp --regex "^user_.*" -c -o /backup/regex/

## 4. 结构和数据分离

# 只备份表结构
mydumper -u root -p password -B myapp --no-data -o /backup/schema_only/

# 只备份数据
mydumper -u root -p password -B myapp --no-schemas -o /backup/data_only/

## 5. 完整备份(包含存储过程、触发器、事件)
mydumper -u root -p password -B myapp --triggers --events --routines -c -o /backup/complete/

## 6. 自动化备份脚本

#!/bin/bash
# mydumper自动化备份脚本

DB_USER="backup_user"
DB_PASS="backup_password"
DB_HOST="localhost"
BACKUP_BASE_DIR="/backup/mydumper"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="$BACKUP_BASE_DIR/backup.log"
THREADS=8
CHUNK_SIZE=100  # MB

# 数据库列表
DATABASES=("myapp1" "myapp2" "myapp3")

# 创建备份目录
mkdir -p $BACKUP_BASE_DIR

echo "$(date): Starting mydumper backup" >> $LOG_FILE

# 备份每个数据库
for DB in "${DATABASES[@]}"; do
    BACKUP_DIR="$BACKUP_BASE_DIR/${DB}_$DATE"
    mkdir -p $BACKUP_DIR
    
    echo "$(date): Backing up database $DB" >> $LOG_FILE
    
    mydumper \
        -h $DB_HOST \
        -u $DB_USER \
        -p $DB_PASS \
        -B $DB \
        --single-transaction \
        --triggers \
        --events \
        --routines \
        -t $THREADS \
        -F $CHUNK_SIZE \
        -c \
        -v 3 \
        -L "$BACKUP_DIR/mydumper.log" \
        -o $BACKUP_DIR
    
    if [ $? -eq 0 ]; then
        echo "$(date): Database $DB backup completed" >> $LOG_FILE
        
        # 创建备份信息文件
        echo "Database: $DB" > "$BACKUP_DIR/backup_info.txt"
        echo "Date: $(date)" >> "$BACKUP_DIR/backup_info.txt"
        echo "Host: $DB_HOST" >> "$BACKUP_DIR/backup_info.txt"
        echo "Threads: $THREADS" >> "$BACKUP_DIR/backup_info.txt"
        echo "Chunk Size: ${CHUNK_SIZE}MB" >> "$BACKUP_DIR/backup_info.txt"
        
        # 计算备份大小
        BACKUP_SIZE=$(du -sh $BACKUP_DIR | cut -f1)
        echo "Backup Size: $BACKUP_SIZE" >> "$BACKUP_DIR/backup_info.txt"
        echo "$(date): Backup size for $DB: $BACKUP_SIZE" >> $LOG_FILE
        
        # 创建压缩包
        cd $BACKUP_BASE_DIR
        tar -czf "${DB}_$DATE.tar.gz" "${DB}_$DATE"
        
        if [ $? -eq 0 ]; then
            echo "$(date): Backup compressed successfully" >> $LOG_FILE
            rm -rf "${DB}_$DATE"  # 删除原始目录
        else
            echo "$(date): ERROR: Failed to compress backup" >> $LOG_FILE
        fi
    else
        echo "$(date): ERROR: Failed to backup database $DB" >> $LOG_FILE
    fi
done

# 清理旧备份(保留7天)
find $BACKUP_BASE_DIR -name "*.tar.gz" -mtime +7 -delete
echo "$(date): Old backups cleaned up" >> $LOG_FILE

echo "$(date): mydumper backup process completed" >> $LOG_FILE
"""
        
        print("\nmydumper使用示例:")
        print("=" * 40)
        print(examples)
    
    def myloader_examples(self):
        """myloader恢复示例"""
        examples = """
myloader恢复示例:

## 1. 基础恢复命令

# 恢复所有数据库
myloader -u root -p password -d /backup/all_databases/

# 恢复到指定数据库
myloader -u root -p password -d /backup/myapp/ -B myapp_restored

# 从源数据库恢复到目标数据库
myloader -u root -p password -d /backup/myapp/ -s myapp -B myapp_test

## 2. 性能优化恢复

# 使用8个并行线程
myloader -u root -p password -t 8 -d /backup/parallel/

# 每次插入1000行
myloader -u root -p password --rows 1000 -d /backup/myapp/

# 使用压缩协议
myloader -u root -p password --compress-protocol -d /backup/myapp/

## 3. 安全恢复选项

# 覆盖已存在的表
myloader -u root -p password -o -d /backup/myapp/

# 跳过触发器
myloader -u root -p password --skip-triggers -d /backup/myapp/

# 启用二进制日志
myloader -u root -p password -e -d /backup/myapp/

## 4. 自动化恢复脚本

#!/bin/bash
# myloader自动化恢复脚本

DB_USER="restore_user"
DB_PASS="restore_password"
DB_HOST="localhost"
BACKUP_FILE="$1"  # 备份文件路径
TARGET_DB="$2"    # 目标数据库名
LOG_FILE="/var/log/mysql_restore.log"
THREADS=4

# 参数检查
if [ $# -ne 2 ]; then
    echo "Usage: $0 <backup_file> <target_database>"
    echo "Example: $0 /backup/myapp_20240115.tar.gz myapp_restored"
    exit 1
fi

# 检查备份文件是否存在
if [ ! -f "$BACKUP_FILE" ]; then
    echo "ERROR: Backup file $BACKUP_FILE not found"
    exit 1
fi

echo "$(date): Starting restore process" >> $LOG_FILE
echo "$(date): Backup file: $BACKUP_FILE" >> $LOG_FILE
echo "$(date): Target database: $TARGET_DB" >> $LOG_FILE

# 创建临时目录
TEMP_DIR="/tmp/mysql_restore_$$"
mkdir -p $TEMP_DIR

# 解压备份文件
echo "$(date): Extracting backup file" >> $LOG_FILE
cd $TEMP_DIR
tar -xzf "$BACKUP_FILE"

if [ $? -ne 0 ]; then
    echo "$(date): ERROR: Failed to extract backup file" >> $LOG_FILE
    rm -rf $TEMP_DIR
    exit 1
fi

# 查找备份目录
BACKUP_DIR=$(find $TEMP_DIR -type d -name "*" | head -2 | tail -1)

if [ ! -d "$BACKUP_DIR" ]; then
    echo "$(date): ERROR: Backup directory not found" >> $LOG_FILE
    rm -rf $TEMP_DIR
    exit 1
fi

echo "$(date): Backup directory: $BACKUP_DIR" >> $LOG_FILE

# 创建目标数据库
echo "$(date): Creating target database" >> $LOG_FILE
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "CREATE DATABASE IF NOT EXISTS $TARGET_DB;"

if [ $? -ne 0 ]; then
    echo "$(date): ERROR: Failed to create target database" >> $LOG_FILE
    rm -rf $TEMP_DIR
    exit 1
fi

# 执行恢复
echo "$(date): Starting data restore" >> $LOG_FILE
myloader \
    -h $DB_HOST \
    -u $DB_USER \
    -p $DB_PASS \
    -B $TARGET_DB \
    -t $THREADS \
    -o \
    -e \
    -v 3 \
    -d $BACKUP_DIR

if [ $? -eq 0 ]; then
    echo "$(date): Restore completed successfully" >> $LOG_FILE
    
    # 验证恢复结果
    TABLE_COUNT=$(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $TARGET_DB -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='$TARGET_DB';" | tail -1)
    echo "$(date): Restored $TABLE_COUNT tables" >> $LOG_FILE
    
    # 检查数据完整性
    mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $TARGET_DB -e "CHECK TABLE $(mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $TARGET_DB -e 'SHOW TABLES;' | tail -n +2 | tr '\n' ',' | sed 's/,$//');" > /tmp/check_result.txt
    
    CORRUPTED_TABLES=$(grep -c "error" /tmp/check_result.txt)
    if [ $CORRUPTED_TABLES -eq 0 ]; then
        echo "$(date): Data integrity check passed" >> $LOG_FILE
    else
        echo "$(date): WARNING: Found $CORRUPTED_TABLES corrupted tables" >> $LOG_FILE
    fi
    
    rm -f /tmp/check_result.txt
else
    echo "$(date): ERROR: Restore failed" >> $LOG_FILE
    rm -rf $TEMP_DIR
    exit 1
fi

# 清理临时文件
rm -rf $TEMP_DIR
echo "$(date): Restore process completed" >> $LOG_FILE

echo "Restore completed successfully!"
echo "Target database: $TARGET_DB"
echo "Restored tables: $TABLE_COUNT"

## 5. 部分恢复脚本

#!/bin/bash
# 部分表恢复脚本

DB_USER="restore_user"
DB_PASS="restore_password"
DB_HOST="localhost"
BACKUP_DIR="$1"     # 备份目录
TARGET_DB="$2"      # 目标数据库
TABLE_LIST="$3"     # 表列表(逗号分隔)

# 参数检查
if [ $# -ne 3 ]; then
    echo "Usage: $0 <backup_dir> <target_database> <table_list>"
    echo "Example: $0 /backup/myapp myapp_test 'users,orders,products'"
    exit 1
fi

# 将表列表转换为数组
IFS=',' read -ra TABLES <<< "$TABLE_LIST"

echo "Restoring tables: ${TABLES[@]}"

# 创建目标数据库
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -e "CREATE DATABASE IF NOT EXISTS $TARGET_DB;"

# 恢复每个表
for TABLE in "${TABLES[@]}"; do
    echo "Restoring table: $TABLE"
    
    # 恢复表结构
    if [ -f "$BACKUP_DIR/$TARGET_DB-schema.sql" ]; then
        grep -A 50 "CREATE TABLE.*$TABLE" "$BACKUP_DIR/$TARGET_DB-schema.sql" | \
        sed '/^CREATE TABLE/,/^)/!d' | \
        mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $TARGET_DB
    fi
    
    # 恢复表数据
    if [ -f "$BACKUP_DIR/$TARGET_DB.$TABLE.sql" ]; then
        mysql -h $DB_HOST -u $DB_USER -p$DB_PASS -D $TARGET_DB < "$BACKUP_DIR/$TARGET_DB.$TABLE.sql"
    fi
    
    echo "Table $TABLE restored"
done

echo "Partial restore completed"
"""
        
        print("\nmyloader恢复示例:")
        print("=" * 40)
        print(examples)

# mydumper实践演示
mydumper_demo = MyDumperPractice()
mydumper_demo.explain_mydumper_options()
mydumper_demo.explain_myloader_options()
mydumper_demo.mydumper_examples()
mydumper_demo.myloader_examples()

7.3 物理备份实践

7.3.1 Percona XtraBackup详解

class XtraBackupPractice:
    def __init__(self):
        self.xtrabackup_options = {
            "连接选项": {
                "--host": "MySQL服务器主机名",
                "--port": "MySQL服务器端口",
                "--user": "连接用户名",
                "--password": "连接密码",
                "--socket": "Unix套接字文件路径",
                "--defaults-file": "MySQL配置文件路径"
            },
            "备份控制": {
                "--backup": "执行备份操作",
                "--target-dir": "备份目标目录",
                "--incremental": "增量备份",
                "--incremental-basedir": "增量备份基础目录",
                "--incremental-dir": "增量备份目录",
                "--databases": "指定要备份的数据库",
                "--tables": "指定要备份的表"
            },
            "性能选项": {
                "--parallel": "并行线程数",
                "--throttle": "限制IO操作数(IOPS)",
                "--use-memory": "prepare阶段使用的内存大小",
                "--compress": "启用压缩",
                "--compress-threads": "压缩线程数",
                "--compress-chunk-size": "压缩块大小"
            },
            "安全选项": {
                "--encrypt": "加密算法(AES128, AES192, AES256)",
                "--encrypt-key": "加密密钥",
                "--encrypt-key-file": "加密密钥文件",
                "--encrypt-threads": "加密线程数",
                "--encrypt-chunk-size": "加密块大小"
            },
            "流式备份": {
                "--stream": "流式输出格式(tar, xbstream)",
                "--tmpdir": "临时目录",
                "--remote-host": "远程主机",
                "--no-timestamp": "不创建时间戳目录"
            },
            "恢复选项": {
                "--prepare": "准备备份进行恢复",
                "--apply-log-only": "只应用日志,不回滚",
                "--copy-back": "复制备份文件到数据目录",
                "--move-back": "移动备份文件到数据目录",
                "--force-non-empty-directories": "强制覆盖非空目录"
            }
        }
        
        self.backup_types = {
            "完全备份": {
                "命令": "xtrabackup --backup --target-dir=/backup/full",
                "说明": "备份所有InnoDB数据和日志",
                "用途": "作为增量备份的基础"
            },
            "增量备份": {
                "命令": "xtrabackup --backup --target-dir=/backup/inc1 --incremental-basedir=/backup/full",
                "说明": "只备份自上次备份以来的变化",
                "用途": "节省存储空间和备份时间"
            },
            "压缩备份": {
                "命令": "xtrabackup --backup --compress --target-dir=/backup/compressed",
                "说明": "备份时进行压缩",
                "用途": "减少存储空间需求"
            },
            "加密备份": {
                "命令": "xtrabackup --backup --encrypt=AES256 --encrypt-key-file=/etc/my.key --target-dir=/backup/encrypted",
                "说明": "备份时进行加密",
                "用途": "保护敏感数据安全"
            },
            "流式备份": {
                "命令": "xtrabackup --backup --stream=xbstream --target-dir=./ | gzip > backup.xbstream.gz",
                "说明": "流式输出备份数据",
                "用途": "直接传输到远程位置"
            }
        }
    
    def explain_options(self):
        """解释XtraBackup选项"""
        print("Percona XtraBackup选项详解:")
        print("=" * 70)
        
        for category, options in self.xtrabackup_options.items():
            print(f"\n{category}:")
            for option, description in options.items():
                print(f"  {option}: {description}")
    
    def show_backup_types(self):
        """显示备份类型"""
        print("\nXtraBackup备份类型:")
        print("=" * 50)
        
        for backup_type, details in self.backup_types.items():
            print(f"\n{backup_type}:")
            print(f"  命令: {details['命令']}")
            print(f"  说明: {details['说明']}")
            print(f"  用途: {details['用途']}")
    
    def backup_examples(self):
        """备份示例"""
        examples = """
Percona XtraBackup备份示例:

## 1. 完全备份

# 基础完全备份
xtrabackup --backup --target-dir=/backup/full_$(date +%Y%m%d)

# 指定MySQL连接参数
xtrabackup --backup \
    --host=localhost \
    --port=3306 \
    --user=backup_user \
    --password=backup_pass \
    --target-dir=/backup/full_$(date +%Y%m%d)

# 备份指定数据库
xtrabackup --backup \
    --databases="myapp1 myapp2" \
    --target-dir=/backup/selected_dbs_$(date +%Y%m%d)

# 并行备份(4个线程)
xtrabackup --backup \
    --parallel=4 \
    --target-dir=/backup/parallel_$(date +%Y%m%d)

## 2. 增量备份

# 第一次增量备份(基于完全备份)
xtrabackup --backup \
    --target-dir=/backup/inc1_$(date +%Y%m%d) \
    --incremental-basedir=/backup/full_20240115

# 第二次增量备份(基于第一次增量备份)
xtrabackup --backup \
    --target-dir=/backup/inc2_$(date +%Y%m%d) \
    --incremental-basedir=/backup/inc1_20240115

# 基于LSN的增量备份
xtrabackup --backup \
    --target-dir=/backup/inc_lsn_$(date +%Y%m%d) \
    --incremental-lsn=1234567890

## 3. 压缩备份

# 基础压缩备份
xtrabackup --backup \
    --compress \
    --target-dir=/backup/compressed_$(date +%Y%m%d)

# 指定压缩线程数和块大小
xtrabackup --backup \
    --compress \
    --compress-threads=4 \
    --compress-chunk-size=64K \
    --target-dir=/backup/compressed_optimized_$(date +%Y%m%d)

# 压缩增量备份
xtrabackup --backup \
    --compress \
    --target-dir=/backup/compressed_inc_$(date +%Y%m%d) \
    --incremental-basedir=/backup/full_20240115

## 4. 加密备份

# 生成加密密钥
openssl rand -base64 24 > /etc/mysql/backup.key
chmod 600 /etc/mysql/backup.key

# 加密备份
xtrabackup --backup \
    --encrypt=AES256 \
    --encrypt-key-file=/etc/mysql/backup.key \
    --target-dir=/backup/encrypted_$(date +%Y%m%d)

# 加密压缩备份
xtrabackup --backup \
    --compress \
    --encrypt=AES256 \
    --encrypt-key-file=/etc/mysql/backup.key \
    --target-dir=/backup/encrypted_compressed_$(date +%Y%m%d)

## 5. 流式备份

# 流式备份到本地文件
xtrabackup --backup \
    --stream=xbstream \
    --target-dir=./ > /backup/stream_$(date +%Y%m%d).xbstream

# 流式备份并压缩
xtrabackup --backup \
    --stream=xbstream \
    --target-dir=./ | gzip > /backup/stream_$(date +%Y%m%d).xbstream.gz

# 流式备份到远程服务器
xtrabackup --backup \
    --stream=xbstream \
    --target-dir=./ | \
    ssh backup_server 'cat > /remote_backup/mysql_$(date +%Y%m%d).xbstream'

# 流式加密压缩备份
xtrabackup --backup \
    --stream=xbstream \
    --compress \
    --encrypt=AES256 \
    --encrypt-key-file=/etc/mysql/backup.key \
    --target-dir=./ | \
    gzip > /backup/secure_stream_$(date +%Y%m%d).xbstream.gz

## 6. 性能优化备份

# 限制IO操作(减少对生产系统的影响)
xtrabackup --backup \
    --throttle=100 \
    --target-dir=/backup/throttled_$(date +%Y%m%d)

# 使用更多内存进行prepare操作
xtrabackup --backup \
    --use-memory=4G \
    --target-dir=/backup/memory_optimized_$(date +%Y%m%d)

# 综合优化备份
xtrabackup --backup \
    --parallel=8 \
    --compress \
    --compress-threads=4 \
    --throttle=200 \
    --use-memory=2G \
    --target-dir=/backup/optimized_$(date +%Y%m%d)

## 7. 自动化备份脚本

#!/bin/bash
# XtraBackup自动化备份脚本

# 配置变量
MYSQL_USER="backup_user"
MYSQL_PASS="backup_password"
MYSQL_HOST="localhost"
MYSQL_PORT="3306"
BACKUP_BASE_DIR="/backup/xtrabackup"
FULL_BACKUP_DIR="$BACKUP_BASE_DIR/full"
INC_BACKUP_DIR="$BACKUP_BASE_DIR/incremental"
LOG_FILE="$BACKUP_BASE_DIR/backup.log"
RETENTION_DAYS=7
PARALLEL_THREADS=4
COMPRESS_THREADS=2
THROTTLE=100

# 创建备份目录
mkdir -p $BACKUP_BASE_DIR $FULL_BACKUP_DIR $INC_BACKUP_DIR

# 日志函数
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" >> $LOG_FILE
    echo "$(date '+%Y-%m-%d %H:%M:%S'): $1"
}

# 检查上次完全备份
LAST_FULL_BACKUP=$(find $FULL_BACKUP_DIR -maxdepth 1 -type d -name "full_*" | sort | tail -1)
DAYS_SINCE_FULL=0

if [ -n "$LAST_FULL_BACKUP" ]; then
    LAST_FULL_DATE=$(basename $LAST_FULL_BACKUP | cut -d'_' -f2)
    DAYS_SINCE_FULL=$(( ($(date +%s) - $(date -d $LAST_FULL_DATE +%s)) / 86400 ))
fi

# 决定备份类型(每周一次完全备份)
if [ $DAYS_SINCE_FULL -ge 7 ] || [ -z "$LAST_FULL_BACKUP" ]; then
    BACKUP_TYPE="full"
    BACKUP_DIR="$FULL_BACKUP_DIR/full_$(date +%Y%m%d_%H%M%S)"
    BASE_DIR_OPTION=""
else
    BACKUP_TYPE="incremental"
    BACKUP_DIR="$INC_BACKUP_DIR/inc_$(date +%Y%m%d_%H%M%S)"
    
    # 查找最新的备份作为基础
    LAST_INC_BACKUP=$(find $INC_BACKUP_DIR -maxdepth 1 -type d -name "inc_*" | sort | tail -1)
    if [ -n "$LAST_INC_BACKUP" ]; then
        BASE_DIR_OPTION="--incremental-basedir=$LAST_INC_BACKUP"
    else
        BASE_DIR_OPTION="--incremental-basedir=$LAST_FULL_BACKUP"
    fi
fi

log_message "Starting $BACKUP_TYPE backup to $BACKUP_DIR"

# 执行备份
if [ "$BACKUP_TYPE" = "full" ]; then
    xtrabackup --backup \
        --host=$MYSQL_HOST \
        --port=$MYSQL_PORT \
        --user=$MYSQL_USER \
        --password=$MYSQL_PASS \
        --parallel=$PARALLEL_THREADS \
        --compress \
        --compress-threads=$COMPRESS_THREADS \
        --throttle=$THROTTLE \
        --target-dir=$BACKUP_DIR
else
    xtrabackup --backup \
        --host=$MYSQL_HOST \
        --port=$MYSQL_PORT \
        --user=$MYSQL_USER \
        --password=$MYSQL_PASS \
        --parallel=$PARALLEL_THREADS \
        --compress \
        --compress-threads=$COMPRESS_THREADS \
        --throttle=$THROTTLE \
        $BASE_DIR_OPTION \
        --target-dir=$BACKUP_DIR
fi

# 检查备份结果
if [ $? -eq 0 ]; then
    log_message "$BACKUP_TYPE backup completed successfully"
    
    # 记录备份信息
    echo "Backup Type: $BACKUP_TYPE" > "$BACKUP_DIR/backup_info.txt"
    echo "Backup Date: $(date)" >> "$BACKUP_DIR/backup_info.txt"
    echo "MySQL Host: $MYSQL_HOST:$MYSQL_PORT" >> "$BACKUP_DIR/backup_info.txt"
    echo "Parallel Threads: $PARALLEL_THREADS" >> "$BACKUP_DIR/backup_info.txt"
    echo "Compress Threads: $COMPRESS_THREADS" >> "$BACKUP_DIR/backup_info.txt"
    echo "Throttle: $THROTTLE IOPS" >> "$BACKUP_DIR/backup_info.txt"
    
    if [ "$BACKUP_TYPE" = "incremental" ]; then
        echo "Base Directory: $(basename $(echo $BASE_DIR_OPTION | cut -d'=' -f2))" >> "$BACKUP_DIR/backup_info.txt"
    fi
    
    # 计算备份大小
    BACKUP_SIZE=$(du -sh $BACKUP_DIR | cut -f1)
    echo "Backup Size: $BACKUP_SIZE" >> "$BACKUP_DIR/backup_info.txt"
    log_message "Backup size: $BACKUP_SIZE"
    
    # 验证备份
    if [ -f "$BACKUP_DIR/xtrabackup_checkpoints" ]; then
        log_message "Backup checkpoints file found - backup appears valid"
    else
        log_message "WARNING: Backup checkpoints file not found"
    fi
else
    log_message "ERROR: $BACKUP_TYPE backup failed"
    exit 1
fi

# 清理旧备份
log_message "Cleaning up old backups (older than $RETENTION_DAYS days)"
find $FULL_BACKUP_DIR -maxdepth 1 -type d -name "full_*" -mtime +$RETENTION_DAYS -exec rm -rf {} \;
find $INC_BACKUP_DIR -maxdepth 1 -type d -name "inc_*" -mtime +$RETENTION_DAYS -exec rm -rf {} \;

log_message "Backup process completed"

# 发送通知(可选)
# echo "MySQL backup completed: $BACKUP_TYPE" | mail -s "MySQL Backup Status" admin@example.com
"""
        
        print("\nXtraBackup备份示例:")
        print("=" * 50)
        print(examples)

# XtraBackup实践演示
xtrabackup_demo = XtraBackupPractice()
xtrabackup_demo.explain_options()
xtrabackup_demo.show_backup_types()
xtrabackup_demo.backup_examples()

7.3.2 XtraBackup恢复实践

class XtraBackupRestore:
    def __init__(self):
        self.restore_steps = {
            "完全备份恢复": [
                "1. 停止MySQL服务",
                "2. 准备备份(xtrabackup --prepare)",
                "3. 恢复数据(xtrabackup --copy-back)",
                "4. 修改文件权限",
                "5. 启动MySQL服务"
            ],
            "增量备份恢复": [
                "1. 停止MySQL服务",
                "2. 准备完全备份(xtrabackup --prepare --apply-log-only)",
                "3. 应用增量备份(xtrabackup --prepare --apply-log-only --incremental-dir)",
                "4. 最终准备(xtrabackup --prepare)",
                "5. 恢复数据(xtrabackup --copy-back)",
                "6. 修改文件权限",
                "7. 启动MySQL服务"
            ],
            "压缩备份恢复": [
                "1. 停止MySQL服务",
                "2. 解压备份文件",
                "3. 准备备份(xtrabackup --prepare)",
                "4. 恢复数据(xtrabackup --copy-back)",
                "5. 修改文件权限",
                "6. 启动MySQL服务"
            ],
            "加密备份恢复": [
                "1. 停止MySQL服务",
                "2. 解密备份文件",
                "3. 准备备份(xtrabackup --prepare)",
                "4. 恢复数据(xtrabackup --copy-back)",
                "5. 修改文件权限",
                "6. 启动MySQL服务"
            ]
        }
    
    def show_restore_steps(self):
        """显示恢复步骤"""
        print("XtraBackup恢复步骤:")
        print("=" * 60)
        
        for restore_type, steps in self.restore_steps.items():
            print(f"\n{restore_type}:")
            for step in steps:
                print(f"  {step}")
    
    def restore_examples(self):
        """恢复示例"""
        examples = """
XtraBackup恢复示例:

## 1. 完全备份恢复

#!/bin/bash
# 完全备份恢复脚本

BACKUP_DIR="/backup/full_20240115"
MYSQL_DATADIR="/var/lib/mysql"
MYSQL_USER="mysql"
MYSQL_GROUP="mysql"

# 停止MySQL服务
sudo systemctl stop mysql

# 备份当前数据目录(可选)
sudo mv $MYSQL_DATADIR $MYSQL_DATADIR.backup.$(date +%Y%m%d_%H%M%S)

# 准备备份
echo "Preparing backup..."
xtrabackup --prepare --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to prepare backup"
    exit 1
fi

# 恢复数据
echo "Restoring data..."
xtrabackup --copy-back --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to restore data"
    exit 1
fi

# 修改文件权限
echo "Setting file permissions..."
sudo chown -R $MYSQL_USER:$MYSQL_GROUP $MYSQL_DATADIR

# 启动MySQL服务
echo "Starting MySQL service..."
sudo systemctl start mysql

if [ $? -eq 0 ]; then
    echo "Restore completed successfully"
else
    echo "ERROR: Failed to start MySQL service"
    exit 1
fi

## 2. 增量备份恢复

#!/bin/bash
# 增量备份恢复脚本

FULL_BACKUP_DIR="/backup/full_20240115"
INC1_BACKUP_DIR="/backup/inc1_20240116"
INC2_BACKUP_DIR="/backup/inc2_20240117"
MYSQL_DATADIR="/var/lib/mysql"
MYSQL_USER="mysql"
MYSQL_GROUP="mysql"

# 停止MySQL服务
sudo systemctl stop mysql

# 备份当前数据目录
sudo mv $MYSQL_DATADIR $MYSQL_DATADIR.backup.$(date +%Y%m%d_%H%M%S)

# 准备完全备份(只应用日志,不回滚)
echo "Preparing full backup..."
xtrabackup --prepare --apply-log-only --target-dir=$FULL_BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to prepare full backup"
    exit 1
fi

# 应用第一个增量备份
echo "Applying first incremental backup..."
xtrabackup --prepare --apply-log-only --target-dir=$FULL_BACKUP_DIR --incremental-dir=$INC1_BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to apply first incremental backup"
    exit 1
fi

# 应用第二个增量备份
echo "Applying second incremental backup..."
xtrabackup --prepare --apply-log-only --target-dir=$FULL_BACKUP_DIR --incremental-dir=$INC2_BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to apply second incremental backup"
    exit 1
fi

# 最终准备(回滚未提交的事务)
echo "Final prepare..."
xtrabackup --prepare --target-dir=$FULL_BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to do final prepare"
    exit 1
fi

# 恢复数据
echo "Restoring data..."
xtrabackup --copy-back --target-dir=$FULL_BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to restore data"
    exit 1
fi

# 修改文件权限
echo "Setting file permissions..."
sudo chown -R $MYSQL_USER:$MYSQL_GROUP $MYSQL_DATADIR

# 启动MySQL服务
echo "Starting MySQL service..."
sudo systemctl start mysql

if [ $? -eq 0 ]; then
    echo "Incremental restore completed successfully"
else
    echo "ERROR: Failed to start MySQL service"
    exit 1
fi

## 3. 压缩备份恢复

#!/bin/bash
# 压缩备份恢复脚本

BACKUP_DIR="/backup/compressed_20240115"
MYSQL_DATADIR="/var/lib/mysql"
MYSQL_USER="mysql"
MYSQL_GROUP="mysql"

# 停止MySQL服务
sudo systemctl stop mysql

# 备份当前数据目录
sudo mv $MYSQL_DATADIR $MYSQL_DATADIR.backup.$(date +%Y%m%d_%H%M%S)

# 解压备份文件
echo "Decompressing backup files..."
for file in $BACKUP_DIR/*.qp; do
    if [ -f "$file" ]; then
        qpress -d "$file" "$(dirname "$file")"
        rm -f "$file"
    fi
done

# 准备备份
echo "Preparing backup..."
xtrabackup --prepare --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to prepare backup"
    exit 1
fi

# 恢复数据
echo "Restoring data..."
xtrabackup --copy-back --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to restore data"
    exit 1
fi

# 修改文件权限
echo "Setting file permissions..."
sudo chown -R $MYSQL_USER:$MYSQL_GROUP $MYSQL_DATADIR

# 启动MySQL服务
echo "Starting MySQL service..."
sudo systemctl start mysql

if [ $? -eq 0 ]; then
    echo "Compressed backup restore completed successfully"
else
    echo "ERROR: Failed to start MySQL service"
    exit 1
fi

## 4. 加密备份恢复

#!/bin/bash
# 加密备份恢复脚本

BACKUP_DIR="/backup/encrypted_20240115"
KEY_FILE="/etc/mysql/backup.key"
MYSQL_DATADIR="/var/lib/mysql"
MYSQL_USER="mysql"
MYSQL_GROUP="mysql"

# 检查密钥文件
if [ ! -f "$KEY_FILE" ]; then
    echo "ERROR: Encryption key file not found: $KEY_FILE"
    exit 1
fi

# 停止MySQL服务
sudo systemctl stop mysql

# 备份当前数据目录
sudo mv $MYSQL_DATADIR $MYSQL_DATADIR.backup.$(date +%Y%m%d_%H%M%S)

# 解密备份文件
echo "Decrypting backup files..."
for file in $BACKUP_DIR/*.xbcrypt; do
    if [ -f "$file" ]; then
        OUTPUT_FILE="${file%.xbcrypt}"
        xbcrypt -d --encrypt-key-file=$KEY_FILE < "$file" > "$OUTPUT_FILE"
        if [ $? -eq 0 ]; then
            rm -f "$file"
        else
            echo "ERROR: Failed to decrypt $file"
            exit 1
        fi
    fi
done

# 如果备份也被压缩,需要解压
for file in $BACKUP_DIR/*.qp; do
    if [ -f "$file" ]; then
        qpress -d "$file" "$(dirname "$file")"
        rm -f "$file"
    fi
done

# 准备备份
echo "Preparing backup..."
xtrabackup --prepare --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to prepare backup"
    exit 1
fi

# 恢复数据
echo "Restoring data..."
xtrabackup --copy-back --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to restore data"
    exit 1
fi

# 修改文件权限
echo "Setting file permissions..."
sudo chown -R $MYSQL_USER:$MYSQL_GROUP $MYSQL_DATADIR

# 启动MySQL服务
echo "Starting MySQL service..."
sudo systemctl start mysql

if [ $? -eq 0 ]; then
    echo "Encrypted backup restore completed successfully"
else
    echo "ERROR: Failed to start MySQL service"
    exit 1
fi

## 5. 流式备份恢复

#!/bin/bash
# 流式备份恢复脚本

STREAM_BACKUP_FILE="/backup/stream_20240115.xbstream.gz"
TEMP_DIR="/tmp/xtrabackup_restore"
MYSQL_DATADIR="/var/lib/mysql"
MYSQL_USER="mysql"
MYSQL_GROUP="mysql"

# 创建临时目录
mkdir -p $TEMP_DIR

# 解压并提取流式备份
echo "Extracting stream backup..."
gunzip -c $STREAM_BACKUP_FILE | xbstream -x -C $TEMP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to extract stream backup"
    rm -rf $TEMP_DIR
    exit 1
fi

# 停止MySQL服务
sudo systemctl stop mysql

# 备份当前数据目录
sudo mv $MYSQL_DATADIR $MYSQL_DATADIR.backup.$(date +%Y%m%d_%H%M%S)

# 如果备份被压缩,需要解压
for file in $TEMP_DIR/*.qp; do
    if [ -f "$file" ]; then
        qpress -d "$file" "$(dirname "$file")"
        rm -f "$file"
    fi
done

# 准备备份
echo "Preparing backup..."
xtrabackup --prepare --target-dir=$TEMP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to prepare backup"
    rm -rf $TEMP_DIR
    exit 1
fi

# 恢复数据
echo "Restoring data..."
xtrabackup --copy-back --target-dir=$TEMP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to restore data"
    rm -rf $TEMP_DIR
    exit 1
fi

# 修改文件权限
echo "Setting file permissions..."
sudo chown -R $MYSQL_USER:$MYSQL_GROUP $MYSQL_DATADIR

# 清理临时目录
rm -rf $TEMP_DIR

# 启动MySQL服务
echo "Starting MySQL service..."
sudo systemctl start mysql

if [ $? -eq 0 ]; then
    echo "Stream backup restore completed successfully"
else
    echo "ERROR: Failed to start MySQL service"
    exit 1
fi

## 6. 部分恢复(表空间恢复)

#!/bin/bash
# 表空间部分恢复脚本

BACKUP_DIR="/backup/full_20240115"
TARGET_DATABASE="myapp"
TARGET_TABLE="users"
MYSQL_DATADIR="/var/lib/mysql"

# 准备备份
echo "Preparing backup..."
xtrabackup --prepare --export --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    echo "ERROR: Failed to prepare backup for export"
    exit 1
fi

# 在目标MySQL中创建表结构
echo "Creating table structure..."
mysql -e "CREATE DATABASE IF NOT EXISTS $TARGET_DATABASE;"
mysql -D $TARGET_DATABASE -e "CREATE TABLE $TARGET_TABLE LIKE $TARGET_DATABASE.$TARGET_TABLE;"

# 丢弃表空间
echo "Discarding tablespace..."
mysql -D $TARGET_DATABASE -e "ALTER TABLE $TARGET_TABLE DISCARD TABLESPACE;"

# 复制表空间文件
echo "Copying tablespace files..."
cp $BACKUP_DIR/$TARGET_DATABASE/$TARGET_TABLE.ibd $MYSQL_DATADIR/$TARGET_DATABASE/
cp $BACKUP_DIR/$TARGET_DATABASE/$TARGET_TABLE.cfg $MYSQL_DATADIR/$TARGET_DATABASE/

# 修改文件权限
chown mysql:mysql $MYSQL_DATADIR/$TARGET_DATABASE/$TARGET_TABLE.*

# 导入表空间
echo "Importing tablespace..."
mysql -D $TARGET_DATABASE -e "ALTER TABLE $TARGET_TABLE IMPORT TABLESPACE;"

if [ $? -eq 0 ]; then
    echo "Partial restore completed successfully"
    # 清理cfg文件
    rm -f $MYSQL_DATADIR/$TARGET_DATABASE/$TARGET_TABLE.cfg
else
    echo "ERROR: Failed to import tablespace"
    exit 1
fi

## 7. 自动化恢复脚本

#!/bin/bash
# 通用自动化恢复脚本

BACKUP_PATH="$1"
RESTORE_TYPE="$2"  # full, incremental, compressed, encrypted, stream
MYSQL_DATADIR="/var/lib/mysql"
MYSQL_USER="mysql"
MYSQL_GROUP="mysql"
TEMP_DIR="/tmp/xtrabackup_restore_$$"
LOG_FILE="/var/log/mysql_restore.log"

# 参数检查
if [ $# -lt 2 ]; then
    echo "Usage: $0 <backup_path> <restore_type>"
    echo "Restore types: full, incremental, compressed, encrypted, stream"
    exit 1
fi

# 日志函数
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a $LOG_FILE
}

# 清理函数
cleanup() {
    if [ -d "$TEMP_DIR" ]; then
        rm -rf $TEMP_DIR
    fi
}

# 设置错误处理
trap cleanup EXIT

log_message "Starting $RESTORE_TYPE restore from $BACKUP_PATH"

# 根据恢复类型执行相应操作
case $RESTORE_TYPE in
    "full")
        BACKUP_DIR=$BACKUP_PATH
        ;;
    "compressed")
        BACKUP_DIR=$BACKUP_PATH
        # 解压文件
        for file in $BACKUP_DIR/*.qp; do
            if [ -f "$file" ]; then
                qpress -d "$file" "$(dirname "$file")"
                rm -f "$file"
            fi
        done
        ;;
    "encrypted")
        BACKUP_DIR=$BACKUP_PATH
        KEY_FILE="/etc/mysql/backup.key"
        # 解密文件
        for file in $BACKUP_DIR/*.xbcrypt; do
            if [ -f "$file" ]; then
                OUTPUT_FILE="${file%.xbcrypt}"
                xbcrypt -d --encrypt-key-file=$KEY_FILE < "$file" > "$OUTPUT_FILE"
                rm -f "$file"
            fi
        done
        ;;
    "stream")
        mkdir -p $TEMP_DIR
        BACKUP_DIR=$TEMP_DIR
        # 提取流式备份
        if [[ $BACKUP_PATH == *.gz ]]; then
            gunzip -c $BACKUP_PATH | xbstream -x -C $TEMP_DIR
        else
            xbstream -x -C $TEMP_DIR < $BACKUP_PATH
        fi
        ;;
    *)
        log_message "ERROR: Unknown restore type: $RESTORE_TYPE"
        exit 1
        ;;
esac

# 停止MySQL服务
log_message "Stopping MySQL service"
sudo systemctl stop mysql

# 备份当前数据目录
if [ -d "$MYSQL_DATADIR" ]; then
    BACKUP_SUFFIX=$(date +%Y%m%d_%H%M%S)
    log_message "Backing up current data directory to $MYSQL_DATADIR.backup.$BACKUP_SUFFIX"
    sudo mv $MYSQL_DATADIR $MYSQL_DATADIR.backup.$BACKUP_SUFFIX
fi

# 准备备份
log_message "Preparing backup"
xtrabackup --prepare --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    log_message "ERROR: Failed to prepare backup"
    exit 1
fi

# 恢复数据
log_message "Restoring data"
xtrabackup --copy-back --target-dir=$BACKUP_DIR

if [ $? -ne 0 ]; then
    log_message "ERROR: Failed to restore data"
    exit 1
fi

# 修改文件权限
log_message "Setting file permissions"
sudo chown -R $MYSQL_USER:$MYSQL_GROUP $MYSQL_DATADIR

# 启动MySQL服务
log_message "Starting MySQL service"
sudo systemctl start mysql

if [ $? -eq 0 ]; then
    log_message "Restore completed successfully"
    
    # 验证恢复结果
    sleep 5
    mysql -e "SELECT 'MySQL is running' AS status;"
    if [ $? -eq 0 ]; then
        log_message "MySQL service is running and responding"
    else
        log_message "WARNING: MySQL service started but not responding"
    fi
else
    log_message "ERROR: Failed to start MySQL service"
    exit 1
fi

log_message "Restore process completed"
"""
        
        print("\nXtraBackup恢复示例:")
        print("=" * 50)
        print(examples)

# XtraBackup恢复演示
xtrabackup_restore_demo = XtraBackupRestore()
xtrabackup_restore_demo.show_restore_steps()
xtrabackup_restore_demo.restore_examples()

7.4 备份监控与验证

7.4.1 备份监控系统

class BackupMonitoring:
    def __init__(self):
        self.monitoring_metrics = {
            "备份成功率": {
                "指标": "backup_success_rate",
                "计算方式": "成功备份次数 / 总备份次数 * 100%",
                "目标值": ">= 99%",
                "告警阈值": "< 95%",
                "监控频率": "每日"
            },
            "备份时间": {
                "指标": "backup_duration",
                "计算方式": "备份结束时间 - 备份开始时间",
                "目标值": "< 预期时间窗口",
                "告警阈值": "> 预期时间的150%",
                "监控频率": "每次备份"
            },
            "备份大小": {
                "指标": "backup_size",
                "计算方式": "备份文件总大小",
                "目标值": "合理范围内",
                "告警阈值": "异常增长或减少",
                "监控频率": "每次备份"
            },
            "存储使用率": {
                "指标": "storage_usage",
                "计算方式": "已使用存储空间 / 总存储空间 * 100%",
                "目标值": "< 80%",
                "告警阈值": "> 90%",
                "监控频率": "每小时"
            },
            "备份完整性": {
                "指标": "backup_integrity",
                "计算方式": "文件校验和验证",
                "目标值": "100%通过",
                "告警阈值": "任何校验失败",
                "监控频率": "每次备份后"
            },
            "恢复测试": {
                "指标": "restore_test_success",
                "计算方式": "恢复测试成功次数 / 总测试次数 * 100%",
                "目标值": "100%",
                "告警阈值": "< 100%",
                "监控频率": "每周"
            }
        }
        
        self.alert_rules = {
            "备份失败": {
                "条件": "备份任务返回非零退出码",
                "级别": "Critical",
                "通知方式": ["邮件", "短信", "钉钉"],
                "处理时间": "立即"
            },
            "备份超时": {
                "条件": "备份时间超过预期150%",
                "级别": "Warning",
                "通知方式": ["邮件", "钉钉"],
                "处理时间": "1小时内"
            },
            "存储空间不足": {
                "条件": "存储使用率 > 90%",
                "级别": "Warning",
                "通知方式": ["邮件", "钉钉"],
                "处理时间": "4小时内"
            },
            "备份文件损坏": {
                "条件": "文件校验和不匹配",
                "级别": "Critical",
                "通知方式": ["邮件", "短信", "钉钉"],
                "处理时间": "立即"
            },
            "恢复测试失败": {
                "条件": "恢复测试不成功",
                "级别": "High",
                "通知方式": ["邮件", "钉钉"],
                "处理时间": "2小时内"
            }
        }
    
    def show_monitoring_metrics(self):
        """显示监控指标"""
        print("备份监控指标:")
        print("=" * 60)
        
        for metric_name, details in self.monitoring_metrics.items():
            print(f"\n{metric_name}:")
            for key, value in details.items():
                print(f"  {key}: {value}")
    
    def show_alert_rules(self):
        """显示告警规则"""
        print("\n告警规则:")
        print("=" * 40)
        
        for alert_name, details in self.alert_rules.items():
            print(f"\n{alert_name}:")
            for key, value in details.items():
                if isinstance(value, list):
                    print(f"  {key}: {', '.join(value)}")
                else:
                    print(f"  {key}: {value}")
    
    def monitoring_implementation(self):
        """监控实现示例"""
        examples = """
备份监控实现示例:

## 1. 备份状态监控脚本

#!/bin/bash
# 备份状态监控脚本

BACKUP_LOG_DIR="/var/log/mysql_backup"
MONITOR_LOG="/var/log/backup_monitor.log"
ALERT_EMAIL="admin@example.com"
WEBHOOK_URL="https://hooks.dingtalk.com/services/xxx"

# 监控函数
monitor_backup_status() {
    local backup_date=$(date +%Y%m%d)
    local backup_log="$BACKUP_LOG_DIR/backup_$backup_date.log"
    
    if [ ! -f "$backup_log" ]; then
        send_alert "ERROR" "Backup log file not found: $backup_log"
        return 1
    fi
    
    # 检查备份是否成功
    if grep -q "backup completed successfully" "$backup_log"; then
        echo "$(date): Backup successful" >> $MONITOR_LOG
        return 0
    else
        send_alert "CRITICAL" "Backup failed - check log: $backup_log"
        return 1
    fi
}

# 监控备份时间
monitor_backup_duration() {
    local backup_log="$1"
    local start_time=$(grep "Starting.*backup" "$backup_log" | tail -1 | awk '{print $1" "$2}')
    local end_time=$(grep "backup completed" "$backup_log" | tail -1 | awk '{print $1" "$2}')
    
    if [ -n "$start_time" ] && [ -n "$end_time" ]; then
        local start_epoch=$(date -d "$start_time" +%s)
        local end_epoch=$(date -d "$end_time" +%s)
        local duration=$((end_epoch - start_epoch))
        
        echo "$(date): Backup duration: ${duration}s" >> $MONITOR_LOG
        
        # 检查是否超时(假设正常备份时间为2小时)
        if [ $duration -gt 10800 ]; then  # 3小时
            send_alert "WARNING" "Backup duration exceeded: ${duration}s"
        fi
    fi
}

# 监控存储空间
monitor_storage_usage() {
    local backup_dir="/backup"
    local usage=$(df "$backup_dir" | awk 'NR==2 {print $5}' | sed 's/%//')
    
    echo "$(date): Storage usage: ${usage}%" >> $MONITOR_LOG
    
    if [ $usage -gt 90 ]; then
        send_alert "WARNING" "Storage usage high: ${usage}%"
    elif [ $usage -gt 95 ]; then
        send_alert "CRITICAL" "Storage usage critical: ${usage}%"
    fi
}

# 发送告警
send_alert() {
    local level="$1"
    local message="$2"
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    
    # 记录告警
    echo "$timestamp [$level] $message" >> $MONITOR_LOG
    
    # 发送邮件
    echo "$message" | mail -s "MySQL Backup Alert [$level]" $ALERT_EMAIL
    
    # 发送钉钉通知
    curl -X POST $WEBHOOK_URL \
        -H 'Content-Type: application/json' \
        -d "{
            \"msgtype\": \"text\",
            \"text\": {
                \"content\": \"MySQL备份告警\\n级别: $level\\n时间: $timestamp\\n消息: $message\"
            }
        }"
}

# 主监控逻辑
main() {
    echo "$(date): Starting backup monitoring" >> $MONITOR_LOG
    
    # 监控备份状态
    monitor_backup_status
    
    # 监控存储使用率
    monitor_storage_usage
    
    # 如果有备份日志,监控备份时间
    local today_log="$BACKUP_LOG_DIR/backup_$(date +%Y%m%d).log"
    if [ -f "$today_log" ]; then
        monitor_backup_duration "$today_log"
    fi
    
    echo "$(date): Backup monitoring completed" >> $MONITOR_LOG
}

# 执行监控
main

## 2. 备份完整性验证脚本

#!/bin/bash
# 备份完整性验证脚本

BACKUP_DIR="/backup"
CHECKSUM_DIR="/backup/checksums"
VERIFY_LOG="/var/log/backup_verify.log"

# 创建校验和
create_checksums() {
    local backup_path="$1"
    local backup_name=$(basename "$backup_path")
    local checksum_file="$CHECKSUM_DIR/${backup_name}.md5"
    
    mkdir -p $CHECKSUM_DIR
    
    echo "$(date): Creating checksums for $backup_name" >> $VERIFY_LOG
    
    if [ -d "$backup_path" ]; then
        # 目录备份
        find "$backup_path" -type f -exec md5sum {} \; > "$checksum_file"
    elif [ -f "$backup_path" ]; then
        # 文件备份
        md5sum "$backup_path" > "$checksum_file"
    else
        echo "$(date): ERROR: Backup path not found: $backup_path" >> $VERIFY_LOG
        return 1
    fi
    
    echo "$(date): Checksums created: $checksum_file" >> $VERIFY_LOG
}

# 验证校验和
verify_checksums() {
    local backup_path="$1"
    local backup_name=$(basename "$backup_path")
    local checksum_file="$CHECKSUM_DIR/${backup_name}.md5"
    
    if [ ! -f "$checksum_file" ]; then
        echo "$(date): ERROR: Checksum file not found: $checksum_file" >> $VERIFY_LOG
        return 1
    fi
    
    echo "$(date): Verifying checksums for $backup_name" >> $VERIFY_LOG
    
    if [ -d "$backup_path" ]; then
        # 验证目录备份
        cd "$(dirname "$backup_path")"
        md5sum -c "$checksum_file"
    elif [ -f "$backup_path" ]; then
        # 验证文件备份
        cd "$(dirname "$backup_path")"
        md5sum -c "$checksum_file"
    fi
    
    if [ $? -eq 0 ]; then
        echo "$(date): Checksum verification passed for $backup_name" >> $VERIFY_LOG
        return 0
    else
        echo "$(date): ERROR: Checksum verification failed for $backup_name" >> $VERIFY_LOG
        return 1
    fi
}

# 验证所有备份
verify_all_backups() {
    local failed_count=0
    local total_count=0
    
    for backup in $BACKUP_DIR/*; do
        if [ -d "$backup" ] || [ -f "$backup" ]; then
            total_count=$((total_count + 1))
            
            if ! verify_checksums "$backup"; then
                failed_count=$((failed_count + 1))
            fi
        fi
    done
    
    echo "$(date): Verification completed - Total: $total_count, Failed: $failed_count" >> $VERIFY_LOG
    
    if [ $failed_count -gt 0 ]; then
        send_alert "CRITICAL" "Backup integrity check failed: $failed_count/$total_count backups corrupted"
        return 1
    else
        echo "$(date): All backups passed integrity check" >> $VERIFY_LOG
        return 0
    fi
}

# 主验证逻辑
main() {
    echo "$(date): Starting backup integrity verification" >> $VERIFY_LOG
    verify_all_backups
    echo "$(date): Backup integrity verification completed" >> $VERIFY_LOG
}

# 执行验证
main

## 3. Prometheus监控配置

# prometheus.yml配置
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'mysql-backup'
    static_configs:
      - targets: ['localhost:9104']
    scrape_interval: 30s
    metrics_path: /metrics

# 备份指标导出器脚本
#!/usr/bin/env python3
# backup_exporter.py

import time
import os
import json
from datetime import datetime, timedelta
from prometheus_client import start_http_server, Gauge, Counter, Histogram
import subprocess

# 定义指标
backup_success_total = Counter('mysql_backup_success_total', 'Total successful backups')
backup_failure_total = Counter('mysql_backup_failure_total', 'Total failed backups')
backup_duration_seconds = Histogram('mysql_backup_duration_seconds', 'Backup duration in seconds')
backup_size_bytes = Gauge('mysql_backup_size_bytes', 'Backup size in bytes', ['backup_type'])
storage_usage_percent = Gauge('mysql_backup_storage_usage_percent', 'Storage usage percentage')
last_backup_timestamp = Gauge('mysql_backup_last_timestamp', 'Timestamp of last backup')

class BackupMetricsCollector:
    def __init__(self, backup_log_dir='/var/log/mysql_backup', backup_dir='/backup'):
        self.backup_log_dir = backup_log_dir
        self.backup_dir = backup_dir
    
    def collect_backup_metrics(self):
        """收集备份指标"""
        try:
            # 检查最近的备份日志
            today = datetime.now().strftime('%Y%m%d')
            log_file = f"{self.backup_log_dir}/backup_{today}.log"
            
            if os.path.exists(log_file):
                with open(log_file, 'r') as f:
                    log_content = f.read()
                
                # 检查备份是否成功
                if 'backup completed successfully' in log_content:
                    backup_success_total.inc()
                    
                    # 更新最后备份时间
                    last_backup_timestamp.set(time.time())
                    
                    # 提取备份时间
                    duration = self.extract_backup_duration(log_content)
                    if duration:
                        backup_duration_seconds.observe(duration)
                else:
                    backup_failure_total.inc()
            
            # 收集备份大小信息
            self.collect_backup_sizes()
            
            # 收集存储使用率
            self.collect_storage_usage()
            
        except Exception as e:
            print(f"Error collecting metrics: {e}")
    
    def extract_backup_duration(self, log_content):
        """从日志中提取备份时间"""
        lines = log_content.split('\n')
        start_time = None
        end_time = None
        
        for line in lines:
            if 'Starting' in line and 'backup' in line:
                start_time = self.parse_log_timestamp(line)
            elif 'backup completed successfully' in line:
                end_time = self.parse_log_timestamp(line)
        
        if start_time and end_time:
            return (end_time - start_time).total_seconds()
        return None
    
    def parse_log_timestamp(self, line):
        """解析日志时间戳"""
        try:
            timestamp_str = line.split(': ')[0]
            return datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S')
        except:
            return None
    
    def collect_backup_sizes(self):
        """收集备份大小"""
        try:
            for item in os.listdir(self.backup_dir):
                item_path = os.path.join(self.backup_dir, item)
                if os.path.isdir(item_path):
                    size = self.get_directory_size(item_path)
                    backup_type = self.determine_backup_type(item)
                    backup_size_bytes.labels(backup_type=backup_type).set(size)
                elif os.path.isfile(item_path):
                    size = os.path.getsize(item_path)
                    backup_type = self.determine_backup_type(item)
                    backup_size_bytes.labels(backup_type=backup_type).set(size)
        except Exception as e:
            print(f"Error collecting backup sizes: {e}")
    
    def get_directory_size(self, path):
        """获取目录大小"""
        total_size = 0
        for dirpath, dirnames, filenames in os.walk(path):
            for filename in filenames:
                filepath = os.path.join(dirpath, filename)
                total_size += os.path.getsize(filepath)
        return total_size
    
    def determine_backup_type(self, name):
        """确定备份类型"""
        if 'full' in name.lower():
            return 'full'
        elif 'inc' in name.lower():
            return 'incremental'
        elif 'compressed' in name.lower():
            return 'compressed'
        else:
            return 'unknown'
    
    def collect_storage_usage(self):
        """收集存储使用率"""
        try:
            result = subprocess.run(['df', self.backup_dir], 
                                  capture_output=True, text=True)
            if result.returncode == 0:
                lines = result.stdout.strip().split('\n')
                if len(lines) >= 2:
                    fields = lines[1].split()
                    if len(fields) >= 5:
                        usage_percent = int(fields[4].rstrip('%'))
                        storage_usage_percent.set(usage_percent)
        except Exception as e:
            print(f"Error collecting storage usage: {e}")

def main():
    # 启动HTTP服务器
    start_http_server(9104)
    
    collector = BackupMetricsCollector()
    
    print("Backup metrics exporter started on port 9104")
    
    while True:
        collector.collect_backup_metrics()
        time.sleep(60)  # 每分钟收集一次指标

if __name__ == '__main__':
    main()

## 4. Grafana仪表板配置

# grafana_dashboard.json
{
  "dashboard": {
    "title": "MySQL Backup Monitoring",
    "panels": [
      {
        "title": "Backup Success Rate",
        "type": "stat",
        "targets": [
          {
            "expr": "rate(mysql_backup_success_total[24h]) / (rate(mysql_backup_success_total[24h]) + rate(mysql_backup_failure_total[24h])) * 100"
          }
        ]
      },
      {
        "title": "Backup Duration",
        "type": "graph",
        "targets": [
          {
            "expr": "mysql_backup_duration_seconds"
          }
        ]
      },
      {
        "title": "Storage Usage",
        "type": "gauge",
        "targets": [
          {
            "expr": "mysql_backup_storage_usage_percent"
          }
        ]
      },
      {
        "title": "Backup Sizes",
        "type": "graph",
        "targets": [
          {
            "expr": "mysql_backup_size_bytes"
          }
        ]
      }
    ]
  }
}

## 5. 定时监控任务

# 添加到crontab
# 每15分钟检查备份状态
*/15 * * * * /opt/scripts/monitor_backup_status.sh

# 每小时检查存储使用率
0 * * * * /opt/scripts/monitor_storage_usage.sh

# 每日验证备份完整性
0 2 * * * /opt/scripts/verify_backup_integrity.sh

# 每周进行恢复测试
0 3 * * 0 /opt/scripts/weekly_restore_test.sh
"""
        
        print("\n监控实现示例:")
        print("=" * 40)
        print(examples)

# 备份监控演示
backup_monitoring_demo = BackupMonitoring()
backup_monitoring_demo.show_monitoring_metrics()
backup_monitoring_demo.show_alert_rules()
backup_monitoring_demo.monitoring_implementation()

7.4.2 备份验证与测试

class BackupValidation:
    def __init__(self):
        self.validation_types = {
            "文件完整性验证": {
                "方法": ["MD5校验", "SHA256校验", "文件大小检查", "文件数量统计"],
                "工具": ["md5sum", "sha256sum", "find", "du"],
                "频率": "每次备份后",
                "自动化": "是"
            },
            "逻辑完整性验证": {
                "方法": ["SQL语法检查", "数据一致性检查", "外键约束验证", "触发器验证"],
                "工具": ["mysql", "mysqlcheck", "pt-table-checksum"],
                "频率": "每日",
                "自动化": "是"
            },
            "恢复测试验证": {
                "方法": ["完整恢复测试", "部分恢复测试", "时间点恢复测试", "跨平台恢复测试"],
                "工具": ["测试环境", "Docker容器", "虚拟机"],
                "频率": "每周",
                "自动化": "部分"
            },
            "性能验证": {
                "方法": ["备份速度测试", "恢复速度测试", "压缩率测试", "存储效率测试"],
                "工具": ["time", "iostat", "sar", "自定义脚本"],
                "频率": "每月",
                "自动化": "是"
            }
        }
        
        self.test_scenarios = {
            "灾难恢复测试": {
                "场景描述": "模拟完全数据丢失,从备份完全恢复",
                "测试步骤": [
                    "1. 停止MySQL服务",
                    "2. 删除或移动数据目录",
                    "3. 从最新备份恢复",
                    "4. 验证数据完整性",
                    "5. 验证应用程序连接",
                    "6. 性能基准测试"
                ],
                "成功标准": "RTO < 4小时,RPO < 1小时,数据完整性100%",
                "测试频率": "每季度"
            },
            "时间点恢复测试": {
                "场景描述": "恢复到特定时间点的数据状态",
                "测试步骤": [
                    "1. 记录当前数据状态",
                    "2. 执行一些数据变更",
                    "3. 恢复到变更前的时间点",
                    "4. 验证数据状态正确",
                    "5. 验证binlog应用正确"
                ],
                "成功标准": "数据状态与预期完全一致",
                "测试频率": "每月"
            },
            "部分恢复测试": {
                "场景描述": "恢复特定数据库或表",
                "测试步骤": [
                    "1. 选择测试目标(数据库/表)",
                    "2. 备份当前状态",
                    "3. 删除目标数据",
                    "4. 从备份恢复目标数据",
                    "5. 验证数据完整性",
                    "6. 验证关联数据一致性"
                ],
                "成功标准": "目标数据完全恢复,其他数据不受影响",
                "测试频率": "每月"
            },
            "跨环境恢复测试": {
                "场景描述": "在不同环境间恢复数据",
                "测试步骤": [
                    "1. 在生产环境创建备份",
                    "2. 传输备份到测试环境",
                    "3. 在测试环境恢复数据",
                    "4. 验证数据完整性",
                    "5. 验证应用程序兼容性",
                    "6. 性能对比测试"
                ],
                "成功标准": "数据完全恢复,应用程序正常运行",
                "测试频率": "每月"
            }
        }
    
    def show_validation_types(self):
        """显示验证类型"""
        print("备份验证类型:")
        print("=" * 60)
        
        for validation_type, details in self.validation_types.items():
            print(f"\n{validation_type}:")
            for key, value in details.items():
                if isinstance(value, list):
                    print(f"  {key}: {', '.join(value)}")
                else:
                    print(f"  {key}: {value}")
    
    def show_test_scenarios(self):
        """显示测试场景"""
        print("\n恢复测试场景:")
        print("=" * 50)
        
        for scenario_name, details in self.test_scenarios.items():
            print(f"\n{scenario_name}:")
            print(f"  场景描述: {details['场景描述']}")
            print(f"  测试步骤:")
            for step in details['测试步骤']:
                print(f"    {step}")
            print(f"  成功标准: {details['成功标准']}")
            print(f"  测试频率: {details['测试频率']}")
    
    def validation_examples(self):
        """验证示例"""
        examples = """
备份验证与测试示例:

## 1. 文件完整性验证脚本

#!/bin/bash
# 备份文件完整性验证脚本

BACKUP_DIR="/backup"
CHECKSUM_DIR="/backup/checksums"
VALIDATION_LOG="/var/log/backup_validation.log"
ALERT_EMAIL="admin@example.com"

# 创建校验和
create_backup_checksum() {
    local backup_path="$1"
    local backup_name=$(basename "$backup_path")
    local checksum_file="$CHECKSUM_DIR/${backup_name}.sha256"
    
    mkdir -p $CHECKSUM_DIR
    
    echo "$(date): Creating checksum for $backup_name" >> $VALIDATION_LOG
    
    if [ -d "$backup_path" ]; then
        # 目录备份
        find "$backup_path" -type f -exec sha256sum {} \; | sort > "$checksum_file"
    elif [ -f "$backup_path" ]; then
        # 文件备份
        sha256sum "$backup_path" > "$checksum_file"
    else
        echo "$(date): ERROR: Backup path not found: $backup_path" >> $VALIDATION_LOG
        return 1
    fi
    
    # 记录备份信息
    echo "$(date): Backup: $backup_name" >> "$checksum_file"
    echo "$(date): Size: $(du -sh \"$backup_path\" | cut -f1)" >> "$checksum_file"
    echo "$(date): Files: $(find \"$backup_path\" -type f | wc -l)" >> "$checksum_file"
    
    echo "$(date): Checksum created: $checksum_file" >> $VALIDATION_LOG
}

# 验证备份完整性
validate_backup_integrity() {
    local backup_path="$1"
    local backup_name=$(basename "$backup_path")
    local checksum_file="$CHECKSUM_DIR/${backup_name}.sha256"
    
    if [ ! -f "$checksum_file" ]; then
        echo "$(date): ERROR: Checksum file not found: $checksum_file" >> $VALIDATION_LOG
        return 1
    fi
    
    echo "$(date): Validating integrity for $backup_name" >> $VALIDATION_LOG
    
    # 验证文件校验和
    local temp_checksum="/tmp/current_checksum_$$"
    
    if [ -d "$backup_path" ]; then
        find "$backup_path" -type f -exec sha256sum {} \; | sort > "$temp_checksum"
    elif [ -f "$backup_path" ]; then
        sha256sum "$backup_path" > "$temp_checksum"
    fi
    
    # 比较校验和(忽略时间戳行)
    if diff <(grep -v "$(date +%Y-%m-%d)" "$checksum_file") <(grep -v "$(date +%Y-%m-%d)" "$temp_checksum") > /dev/null; then
        echo "$(date): Integrity validation PASSED for $backup_name" >> $VALIDATION_LOG
        rm -f "$temp_checksum"
        return 0
    else
        echo "$(date): ERROR: Integrity validation FAILED for $backup_name" >> $VALIDATION_LOG
        
        # 发送告警
        echo "Backup integrity validation failed for $backup_name" | \
            mail -s "CRITICAL: Backup Integrity Failure" $ALERT_EMAIL
        
        rm -f "$temp_checksum"
        return 1
    fi
}

# 验证所有备份
validate_all_backups() {
    local total_backups=0
    local failed_validations=0
    
    echo "$(date): Starting backup integrity validation" >> $VALIDATION_LOG
    
    for backup in $BACKUP_DIR/*; do
        if [ -d "$backup" ] || [ -f "$backup" ]; then
            # 跳过校验和目录
            if [[ "$(basename \"$backup\")" == "checksums" ]]; then
                continue
            fi
            
            total_backups=$((total_backups + 1))
            
            if ! validate_backup_integrity "$backup"; then
                failed_validations=$((failed_validations + 1))
            fi
        fi
    done
    
    echo "$(date): Validation completed - Total: $total_backups, Failed: $failed_validations" >> $VALIDATION_LOG
    
    if [ $failed_validations -gt 0 ]; then
        echo "$(date): WARNING: $failed_validations backup(s) failed integrity validation" >> $VALIDATION_LOG
        return 1
    else
        echo "$(date): All backups passed integrity validation" >> $VALIDATION_LOG
        return 0
    fi
}

# 主函数
main() {
    case "$1" in
        "create")
            if [ -z "$2" ]; then
                echo "Usage: $0 create <backup_path>"
                exit 1
            fi
            create_backup_checksum "$2"
            ;;
        "validate")
            if [ -z "$2" ]; then
                validate_all_backups
            else
                validate_backup_integrity "$2"
            fi
            ;;
        *)
            echo "Usage: $0 {create|validate} [backup_path]"
            echo "  create <path>  - Create checksum for specific backup"
            echo "  validate [path] - Validate specific backup or all backups"
            exit 1
            ;;
    esac
}

# 执行主函数
main "$@"

## 2. 逻辑完整性验证脚本

#!/bin/bash
# MySQL逻辑完整性验证脚本

MYSQL_USER="backup_user"
MYSQL_PASSWORD="backup_password"
MYSQL_HOST="localhost"
MYSQL_PORT="3306"
VALIDATION_LOG="/var/log/mysql_logical_validation.log"
TEMP_DIR="/tmp/mysql_validation_$$"

# 创建临时目录
mkdir -p $TEMP_DIR

# 清理函数
cleanup() {
    rm -rf $TEMP_DIR
}

# 设置清理陷阱
trap cleanup EXIT

# 日志函数
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a $VALIDATION_LOG
}

# 检查MySQL连接
check_mysql_connection() {
    mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -e "SELECT 1" > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        log_message "MySQL connection successful"
        return 0
    else
        log_message "ERROR: MySQL connection failed"
        return 1
    fi
}

# 检查数据库结构
validate_database_structure() {
    local database="$1"
    
    log_message "Validating structure for database: $database"
    
    # 检查表结构
    mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD \
        -e "USE $database; SHOW TABLES;" > "$TEMP_DIR/tables_$database.txt" 2>/dev/null
    
    if [ $? -ne 0 ]; then
        log_message "ERROR: Failed to get table list for database $database"
        return 1
    fi
    
    local table_count=$(wc -l < "$TEMP_DIR/tables_$database.txt")
    log_message "Database $database has $table_count tables"
    
    # 检查每个表的结构
    while read -r table; do
        if [ -n "$table" ] && [ "$table" != "Tables_in_$database" ]; then
            mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD \
                -e "USE $database; DESCRIBE $table;" > /dev/null 2>&1
            
            if [ $? -ne 0 ]; then
                log_message "ERROR: Table $table in database $database has structure issues"
                return 1
            fi
        fi
    done < "$TEMP_DIR/tables_$database.txt"
    
    log_message "Database structure validation passed for $database"
    return 0
}

# 检查数据一致性
validate_data_consistency() {
    local database="$1"
    
    log_message "Validating data consistency for database: $database"
    
    # 检查外键约束
    mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD \
        -e "USE $database; 
            SELECT TABLE_NAME, CONSTRAINT_NAME 
            FROM information_schema.TABLE_CONSTRAINTS 
            WHERE CONSTRAINT_TYPE = 'FOREIGN KEY' 
            AND TABLE_SCHEMA = '$database';" > "$TEMP_DIR/foreign_keys_$database.txt"
    
    # 检查数据完整性
    mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD \
        -e "USE $database; CHECK TABLE $(mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD -e \"USE $database; SHOW TABLES;\" | tail -n +2 | tr '\n' ',' | sed 's/,$//');" \
        > "$TEMP_DIR/check_result_$database.txt" 2>&1
    
    # 分析检查结果
    if grep -q "error" "$TEMP_DIR/check_result_$database.txt"; then
        log_message "ERROR: Data consistency issues found in database $database"
        cat "$TEMP_DIR/check_result_$database.txt" >> $VALIDATION_LOG
        return 1
    else
        log_message "Data consistency validation passed for $database"
        return 0
    fi
}

# 验证备份文件的SQL语法
validate_sql_syntax() {
    local backup_file="$1"
    
    log_message "Validating SQL syntax in backup file: $backup_file"
    
    # 检查文件是否存在
    if [ ! -f "$backup_file" ]; then
        log_message "ERROR: Backup file not found: $backup_file"
        return 1
    fi
    
    # 创建临时数据库进行语法检查
    local temp_db="syntax_check_$(date +%s)"
    
    mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD \
        -e "CREATE DATABASE $temp_db;" 2>/dev/null
    
    if [ $? -ne 0 ]; then
        log_message "ERROR: Failed to create temporary database for syntax check"
        return 1
    fi
    
    # 尝试导入备份文件
    mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD \
        $temp_db < "$backup_file" > "$TEMP_DIR/syntax_check.log" 2>&1
    
    local import_result=$?
    
    # 清理临时数据库
    mysql -h$MYSQL_HOST -P$MYSQL_PORT -u$MYSQL_USER -p$MYSQL_PASSWORD \
        -e "DROP DATABASE $temp_db;" 2>/dev/null
    
    if [ $import_result -eq 0 ]; then
        log_message "SQL syntax validation passed for $backup_file"
        return 0
    else
        log_message "ERROR: SQL syntax issues found in $backup_file"
        cat "$TEMP_DIR/syntax_check.log" >> $VALIDATION_LOG
        return 1
    fi
}

# 主验证函数
main() {
    log_message "Starting MySQL logical validation"
    
    # 检查MySQL连接
    if ! check_mysql_connection; then
        exit 1
    fi
    
    case "$1" in
        "structure")
            if [ -z "$2" ]; then
                log_message "ERROR: Database name required for structure validation"
                exit 1
            fi
            validate_database_structure "$2"
            ;;
        "consistency")
            if [ -z "$2" ]; then
                log_message "ERROR: Database name required for consistency validation"
                exit 1
            fi
            validate_data_consistency "$2"
            ;;
        "syntax")
            if [ -z "$2" ]; then
                log_message "ERROR: Backup file path required for syntax validation"
                exit 1
            fi
            validate_sql_syntax "$2"
            ;;
        "all")
            if [ -z "$2" ]; then
                log_message "ERROR: Database name required for full validation"
                exit 1
            fi
            
            local database="$2"
            local validation_failed=0
            
            if ! validate_database_structure "$database"; then
                validation_failed=1
            fi
            
            if ! validate_data_consistency "$database"; then
                validation_failed=1
            fi
            
            if [ $validation_failed -eq 0 ]; then
                log_message "All logical validations passed for database $database"
            else
                log_message "Some logical validations failed for database $database"
                exit 1
            fi
            ;;
        *)
            echo "Usage: $0 {structure|consistency|syntax|all} <database_name|backup_file>"
            echo "  structure <db>    - Validate database structure"
            echo "  consistency <db>  - Validate data consistency"
            echo "  syntax <file>     - Validate SQL syntax in backup file"
            echo "  all <db>          - Run all validations for database"
            exit 1
            ;;
    esac
    
    log_message "MySQL logical validation completed"
}

# 执行主函数
main "$@"

## 3. 自动化恢复测试脚本

#!/bin/bash
# 自动化恢复测试脚本

TEST_CONFIG_FILE="/etc/mysql/restore_test.conf"
TEST_LOG="/var/log/mysql_restore_test.log"
TEST_RESULTS_DIR="/var/log/restore_test_results"
ALERT_EMAIL="admin@example.com"

# 默认配置
TEST_MYSQL_USER="test_user"
TEST_MYSQL_PASSWORD="test_password"
TEST_MYSQL_HOST="localhost"
TEST_MYSQL_PORT="3307"  # 使用不同端口避免冲突
TEST_DATA_DIR="/var/lib/mysql_test"
BACKUP_DIR="/backup"
TEST_DATABASE="restore_test_db"

# 加载配置文件
if [ -f "$TEST_CONFIG_FILE" ]; then
    source "$TEST_CONFIG_FILE"
fi

# 创建结果目录
mkdir -p $TEST_RESULTS_DIR

# 日志函数
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a $TEST_LOG
}

# 发送测试报告
send_test_report() {
    local test_type="$1"
    local result="$2"
    local details="$3"
    
    local subject="MySQL Restore Test Report - $test_type"
    local body="Test Type: $test_type\nResult: $result\nTimestamp: $(date)\n\nDetails:\n$details"
    
    echo -e "$body" | mail -s "$subject" $ALERT_EMAIL
}

# 启动测试MySQL实例
start_test_mysql() {
    log_message "Starting test MySQL instance"
    
    # 检查测试实例是否已运行
    if mysqladmin -h$TEST_MYSQL_HOST -P$TEST_MYSQL_PORT ping > /dev/null 2>&1; then
        log_message "Test MySQL instance already running"
        return 0
    fi
    
    # 创建测试数据目录
    mkdir -p $TEST_DATA_DIR
    
    # 初始化测试数据库
    if [ ! -f "$TEST_DATA_DIR/mysql/user.frm" ]; then
        log_message "Initializing test MySQL data directory"
        mysql_install_db --datadir=$TEST_DATA_DIR --user=mysql
    fi
    
    # 启动测试MySQL实例
    mysqld_safe --datadir=$TEST_DATA_DIR \
                --port=$TEST_MYSQL_PORT \
                --socket=/tmp/mysql_test.sock \
                --pid-file=/tmp/mysql_test.pid \
                --log-error=/tmp/mysql_test.err \
                --user=mysql &
    
    # 等待启动
    local wait_count=0
    while [ $wait_count -lt 30 ]; do
        if mysqladmin -h$TEST_MYSQL_HOST -P$TEST_MYSQL_PORT ping > /dev/null 2>&1; then
            log_message "Test MySQL instance started successfully"
            return 0
        fi
        sleep 2
        wait_count=$((wait_count + 1))
    done
    
    log_message "ERROR: Failed to start test MySQL instance"
    return 1
}

# 停止测试MySQL实例
stop_test_mysql() {
    log_message "Stopping test MySQL instance"
    
    if [ -f "/tmp/mysql_test.pid" ]; then
        local pid=$(cat /tmp/mysql_test.pid)
        kill $pid
        
        # 等待停止
        local wait_count=0
        while [ $wait_count -lt 10 ]; do
            if ! kill -0 $pid 2>/dev/null; then
                log_message "Test MySQL instance stopped successfully"
                rm -f /tmp/mysql_test.pid /tmp/mysql_test.sock
                return 0
            fi
            sleep 1
            wait_count=$((wait_count + 1))
        done
        
        # 强制停止
        kill -9 $pid 2>/dev/null
        rm -f /tmp/mysql_test.pid /tmp/mysql_test.sock
    fi
    
    log_message "Test MySQL instance stopped"
}

# 完整恢复测试
test_full_restore() {
    local backup_path="$1"
    local test_name="full_restore_$(date +%Y%m%d_%H%M%S)"
    local result_file="$TEST_RESULTS_DIR/$test_name.log"
    
    log_message "Starting full restore test with backup: $backup_path"
    
    # 记录开始时间
    local start_time=$(date +%s)
    
    {
        echo "=== Full Restore Test ==="
        echo "Test Name: $test_name"
        echo "Backup Path: $backup_path"
        echo "Start Time: $(date)"
        echo ""
        
        # 停止测试实例
        stop_test_mysql
        
        # 清理测试数据目录
        rm -rf $TEST_DATA_DIR/*
        
        # 根据备份类型进行恢复
        if [[ "$backup_path" == *.sql ]]; then
            # 逻辑备份恢复
            echo "Restoring from logical backup..."
            
            # 启动测试实例
            if ! start_test_mysql; then
                echo "ERROR: Failed to start test MySQL instance"
                return 1
            fi
            
            # 创建测试数据库
            mysql -h$TEST_MYSQL_HOST -P$TEST_MYSQL_PORT \
                  -e "CREATE DATABASE $TEST_DATABASE;"
            
            # 导入备份
            mysql -h$TEST_MYSQL_HOST -P$TEST_MYSQL_PORT \
                  $TEST_DATABASE < "$backup_path"
            
            if [ $? -eq 0 ]; then
                echo "Logical backup restore completed successfully"
            else
                echo "ERROR: Logical backup restore failed"
                return 1
            fi
            
        else
            # 物理备份恢复
            echo "Restoring from physical backup..."
            
            # 准备备份
            xtrabackup --prepare --target-dir="$backup_path"
            
            if [ $? -ne 0 ]; then
                echo "ERROR: Failed to prepare backup"
                return 1
            fi
            
            # 恢复数据
            xtrabackup --copy-back --target-dir="$backup_path" --datadir="$TEST_DATA_DIR"
            
            if [ $? -ne 0 ]; then
                echo "ERROR: Failed to copy back data"
                return 1
            fi
            
            # 修改权限
            chown -R mysql:mysql $TEST_DATA_DIR
            
            # 启动测试实例
            if ! start_test_mysql; then
                echo "ERROR: Failed to start test MySQL instance after restore"
                return 1
            fi
            
            echo "Physical backup restore completed successfully"
        fi
        
        # 验证恢复结果
        echo "Validating restore results..."
        
        # 检查数据库连接
        mysql -h$TEST_MYSQL_HOST -P$TEST_MYSQL_PORT -e "SELECT 1" > /dev/null
        if [ $? -eq 0 ]; then
            echo "Database connection: OK"
        else
            echo "ERROR: Database connection failed"
            return 1
        fi
        
        # 检查数据库列表
        local db_count=$(mysql -h$TEST_MYSQL_HOST -P$TEST_MYSQL_PORT \
                        -e "SHOW DATABASES;" | wc -l)
        echo "Database count: $db_count"
        
        # 检查表数量
        local table_count=$(mysql -h$TEST_MYSQL_HOST -P$TEST_MYSQL_PORT \
                           -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema', 'mysql', 'performance_schema', 'sys');" | tail -1)
        echo "Table count: $table_count"
        
        # 记录结束时间
        local end_time=$(date +%s)
        local duration=$((end_time - start_time))
        
        echo ""
        echo "Test completed successfully"
        echo "Duration: ${duration} seconds"
        echo "End Time: $(date)"
        
    } > "$result_file" 2>&1
    
    log_message "Full restore test completed successfully: $test_name"
    send_test_report "Full Restore" "SUCCESS" "$(cat $result_file)"
    
    return 0
}

# 时间点恢复测试
test_point_in_time_restore() {
    local backup_path="$1"
    local target_time="$2"
    local test_name="pitr_$(date +%Y%m%d_%H%M%S)"
    local result_file="$TEST_RESULTS_DIR/$test_name.log"
    
    log_message "Starting point-in-time restore test to: $target_time"
    
    {
        echo "=== Point-in-Time Restore Test ==="
        echo "Test Name: $test_name"
        echo "Backup Path: $backup_path"
        echo "Target Time: $target_time"
        echo "Start Time: $(date)"
        echo ""
        
        # 这里实现时间点恢复逻辑
        # 由于篇幅限制,这里只是示例框架
        echo "Point-in-time restore test implementation..."
        
        echo "Test completed"
        echo "End Time: $(date)"
        
    } > "$result_file" 2>&1
    
    log_message "Point-in-time restore test completed: $test_name"
    send_test_report "Point-in-Time Restore" "SUCCESS" "$(cat $result_file)"
}

# 性能基准测试
run_performance_benchmark() {
    local test_name="performance_$(date +%Y%m%d_%H%M%S)"
    local result_file="$TEST_RESULTS_DIR/$test_name.log"
    
    log_message "Running performance benchmark test"
    
    {
        echo "=== Performance Benchmark Test ==="
        echo "Test Name: $test_name"
        echo "Start Time: $(date)"
        echo ""
        
        # 运行sysbench测试
        if command -v sysbench > /dev/null; then
            echo "Running sysbench OLTP test..."
            
            # 准备测试数据
            sysbench oltp_read_write \
                --mysql-host=$TEST_MYSQL_HOST \
                --mysql-port=$TEST_MYSQL_PORT \
                --mysql-db=$TEST_DATABASE \
                --tables=10 \
                --table-size=10000 \
                prepare
            
            # 运行测试
            sysbench oltp_read_write \
                --mysql-host=$TEST_MYSQL_HOST \
                --mysql-port=$TEST_MYSQL_PORT \
                --mysql-db=$TEST_DATABASE \
                --tables=10 \
                --table-size=10000 \
                --threads=10 \
                --time=60 \
                run
            
            # 清理测试数据
            sysbench oltp_read_write \
                --mysql-host=$TEST_MYSQL_HOST \
                --mysql-port=$TEST_MYSQL_PORT \
                --mysql-db=$TEST_DATABASE \
                --tables=10 \
                cleanup
        else
            echo "sysbench not available, skipping performance test"
        fi
        
        echo "Performance benchmark completed"
        echo "End Time: $(date)"
        
    } > "$result_file" 2>&1
    
    log_message "Performance benchmark test completed: $test_name"
    send_test_report "Performance Benchmark" "SUCCESS" "$(cat $result_file)"
}

# 主测试函数
main() {
    log_message "Starting automated restore testing"
    
    case "$1" in
        "full")
            if [ -z "$2" ]; then
                echo "Usage: $0 full <backup_path>"
                exit 1
            fi
            test_full_restore "$2"
            ;;
        "pitr")
            if [ -z "$2" ] || [ -z "$3" ]; then
                echo "Usage: $0 pitr <backup_path> <target_time>"
                exit 1
            fi
            test_point_in_time_restore "$2" "$3"
            ;;
        "performance")
            run_performance_benchmark
            ;;
        "all")
            if [ -z "$2" ]; then
                echo "Usage: $0 all <backup_path>"
                exit 1
            fi
            
            # 运行所有测试
            test_full_restore "$2"
            run_performance_benchmark
            
            log_message "All restore tests completed"
            ;;
        "cleanup")
            stop_test_mysql
            rm -rf $TEST_DATA_DIR
            log_message "Test environment cleaned up"
            ;;
        *)
            echo "Usage: $0 {full|pitr|performance|all|cleanup} [options]"
            echo "  full <backup_path>              - Test full restore"
            echo "  pitr <backup_path> <time>       - Test point-in-time restore"
            echo "  performance                     - Run performance benchmark"
            echo "  all <backup_path>               - Run all tests"
            echo "  cleanup                         - Clean up test environment"
            exit 1
            ;;
    esac
    
    log_message "Automated restore testing completed"
}

# 设置清理陷阱
trap 'stop_test_mysql' EXIT

# 执行主函数
main "$@"
"""
        
        print("\n备份验证与测试示例:")
        print("=" * 50)
        print(examples)

# 备份验证演示
backup_validation_demo = BackupValidation()
backup_validation_demo.show_validation_types()
backup_validation_demo.show_test_scenarios()
backup_validation_demo.validation_examples()

7.5 备份最佳实践

7.5.1 备份策略设计

class BackupBestPractices:
    def __init__(self):
        self.strategy_principles = {
            "3-2-1原则": {
                "描述": "至少3份数据副本,存储在2种不同介质,1份异地存储",
                "实施要点": [
                    "生产数据库(原始数据)",
                    "本地备份存储(磁盘阵列)",
                    "远程备份存储(云存储/异地机房)"
                ],
                "优势": "最大化数据安全性,防范多种风险",
                "成本": "中等到高"
            },
            "RTO/RPO平衡": {
                "描述": "恢复时间目标与恢复点目标的平衡",
                "考虑因素": [
                    "业务重要性等级",
                    "数据变化频率",
                    "可接受的数据丢失量",
                    "可接受的停机时间",
                    "成本预算限制"
                ],
                "实施策略": "根据业务需求分级制定不同的备份策略"
            },
            "分层备份策略": {
                "描述": "根据数据重要性和访问频率制定不同备份策略",
                "层级划分": {
                    "核心业务数据": "实时复制 + 每小时增量 + 每日全量",
                    "重要业务数据": "每4小时增量 + 每日全量",
                    "一般业务数据": "每日增量 + 每周全量",
                    "历史归档数据": "每月全量备份"
                }
            }
        }
        
        self.implementation_guidelines = {
            "备份时间规划": {
                "原则": "避开业务高峰期,确保备份质量",
                "建议时间窗口": {
                    "全量备份": "凌晨2:00-6:00(业务低峰期)",
                    "增量备份": "每4小时一次,避开高峰",
                    "日志备份": "每15分钟一次,持续进行"
                },
                "注意事项": [
                    "考虑时区差异",
                    "避免与其他维护任务冲突",
                    "预留足够的备份时间窗口",
                    "监控备份完成时间趋势"
                ]
            },
            "存储规划": {
                "容量规划": {
                    "计算公式": "备份存储 = 数据库大小 × 压缩率 × 保留周期 × 备份频率",
                    "预留空间": "建议预留30-50%的额外空间",
                    "增长预测": "基于历史数据预测未来6-12个月的存储需求"
                },
                "存储介质选择": {
                    "SSD": "快速备份和恢复,适合频繁访问的备份",
                    "机械硬盘": "成本效益高,适合长期存储",
                    "磁带": "超长期归档,成本最低",
                    "云存储": "弹性扩展,异地容灾"
                },
                "存储架构": {
                    "本地存储": "快速恢复,但存在单点风险",
                    "网络存储": "集中管理,便于共享",
                    "云存储": "无限扩展,地理分布",
                    "混合存储": "结合多种存储优势"
                }
            },
            "安全考虑": {
                "数据加密": {
                    "传输加密": "使用SSL/TLS加密备份传输",
                    "存储加密": "备份文件静态加密存储",
                    "密钥管理": "安全的密钥存储和轮换机制"
                },
                "访问控制": {
                    "最小权限原则": "仅授予必要的备份和恢复权限",
                    "身份认证": "强身份认证和多因素认证",
                    "审计日志": "记录所有备份相关操作"
                },
                "合规要求": {
                    "数据保护法规": "GDPR、CCPA等数据保护要求",
                    "行业标准": "SOX、HIPAA、PCI-DSS等合规要求",
                    "数据驻留": "满足数据本地化要求"
                }
            }
        }
        
        self.automation_practices = {
            "自动化备份": {
                "调度系统": ["Cron", "Jenkins", "Ansible", "Kubernetes CronJob"],
                "监控集成": ["Prometheus", "Grafana", "Zabbix", "Nagios"],
                "告警机制": ["Email", "SMS", "Slack", "PagerDuty"],
                "自愈能力": "备份失败自动重试和故障转移"
            },
            "智能化管理": {
                "动态调度": "根据系统负载动态调整备份时间",
                "智能压缩": "根据数据特征选择最优压缩算法",
                "预测性维护": "基于历史数据预测备份问题",
                "自动清理": "根据保留策略自动清理过期备份"
            }
        }
    
    def show_strategy_principles(self):
        """显示策略原则"""
        print("备份策略设计原则:")
        print("=" * 60)
        
        for principle, details in self.strategy_principles.items():
            print(f"\n{principle}:")
            print(f"  描述: {details['描述']}")
            
            if '实施要点' in details:
                print(f"  实施要点:")
                for point in details['实施要点']:
                    print(f"    • {point}")
            
            if '考虑因素' in details:
                print(f"  考虑因素:")
                for factor in details['考虑因素']:
                    print(f"    • {factor}")
            
            if '层级划分' in details:
                print(f"  层级划分:")
                for level, strategy in details['层级划分'].items():
                    print(f"    • {level}: {strategy}")
            
            if '优势' in details:
                print(f"  优势: {details['优势']}")
            if '成本' in details:
                print(f"  成本: {details['成本']}")
            if '实施策略' in details:
                print(f"  实施策略: {details['实施策略']}")
    
    def show_implementation_guidelines(self):
        """显示实施指南"""
        print("\n备份实施指南:")
        print("=" * 50)
        
        for guideline, details in self.implementation_guidelines.items():
            print(f"\n{guideline}:")
            
            if isinstance(details, dict):
                for key, value in details.items():
                    if isinstance(value, dict):
                        print(f"  {key}:")
                        for sub_key, sub_value in value.items():
                            if isinstance(sub_value, list):
                                print(f"    {sub_key}:")
                                for item in sub_value:
                                    print(f"      • {item}")
                            else:
                                print(f"    {sub_key}: {sub_value}")
                    elif isinstance(value, list):
                        print(f"  {key}:")
                        for item in value:
                            print(f"    • {item}")
                    else:
                        print(f"  {key}: {value}")
    
    def show_automation_practices(self):
        """显示自动化实践"""
        print("\n自动化最佳实践:")
        print("=" * 50)
        
        for practice, details in self.automation_practices.items():
            print(f"\n{practice}:")
            for key, value in details.items():
                if isinstance(value, list):
                    print(f"  {key}: {', '.join(value)}")
                else:
                    print(f"  {key}: {value}")
    
    def backup_checklist(self):
        """备份检查清单"""
        checklist = """
备份实施检查清单:

## 备份策略检查
□ 已定义RTO和RPO目标
□ 已制定分层备份策略
□ 已规划备份时间窗口
□ 已评估存储容量需求
□ 已选择合适的备份工具
□ 已设计备份保留策略

## 技术实施检查
□ 备份脚本已编写和测试
□ 自动化调度已配置
□ 监控和告警已设置
□ 备份加密已启用
□ 访问控制已配置
□ 网络带宽已评估

## 存储和安全检查
□ 本地存储已配置
□ 远程存储已配置
□ 存储权限已设置
□ 备份传输加密已启用
□ 备份文件加密已启用
□ 密钥管理已实施

## 测试和验证检查
□ 备份完整性验证已实施
□ 恢复测试已执行
□ 性能基准已建立
□ 故障场景已测试
□ 文档已编写和更新
□ 团队培训已完成

## 运维和维护检查
□ 监控仪表板已配置
□ 告警规则已设置
□ 日志分析已实施
□ 定期审查已安排
□ 容量规划已更新
□ 灾难恢复计划已制定

## 合规和审计检查
□ 数据保护要求已满足
□ 行业合规已验证
□ 审计日志已启用
□ 数据驻留要求已满足
□ 保留策略已实施
□ 数据销毁程序已定义
"""
        
        print("\n备份实施检查清单:")
        print("=" * 50)
        print(checklist)

# 备份最佳实践演示
backup_best_practices_demo = BackupBestPractices()
backup_best_practices_demo.show_strategy_principles()
backup_best_practices_demo.show_implementation_guidelines()
backup_best_practices_demo.show_automation_practices()
backup_best_practices_demo.backup_checklist()

7.5.2 常见问题与解决方案

class BackupTroubleshooting:
    def __init__(self):
        self.common_issues = {
            "备份失败问题": {
                "磁盘空间不足": {
                    "症状": ["备份中断", "错误日志显示空间不足", "备份文件不完整"],
                    "原因": ["备份目录空间不足", "临时空间不足", "日志文件占用过多空间"],
                    "解决方案": [
                        "清理过期备份文件",
                        "扩展存储容量",
                        "优化备份压缩设置",
                        "实施自动清理策略",
                        "监控磁盘使用率"
                    ],
                    "预防措施": ["设置磁盘使用率告警", "定期容量规划", "自动化清理脚本"]
                },
                "网络连接问题": {
                    "症状": ["远程备份失败", "传输中断", "连接超时"],
                    "原因": ["网络不稳定", "防火墙阻断", "带宽不足", "DNS解析问题"],
                    "解决方案": [
                        "检查网络连通性",
                        "配置防火墙规则",
                        "优化网络带宽",
                        "使用断点续传",
                        "配置网络重试机制"
                    ],
                    "预防措施": ["网络监控", "冗余网络路径", "带宽预留"]
                },
                "权限问题": {
                    "症状": ["访问被拒绝", "无法创建备份文件", "无法读取数据库"],
                    "原因": ["MySQL用户权限不足", "文件系统权限不足", "SELinux策略限制"],
                    "解决方案": [
                        "检查MySQL用户权限",
                        "调整文件系统权限",
                        "配置SELinux策略",
                        "使用专用备份用户",
                        "验证权限配置"
                    ],
                    "预防措施": ["权限审计", "最小权限原则", "定期权限检查"]
                },
                "锁等待超时": {
                    "症状": ["备份挂起", "锁等待超时错误", "备份时间过长"],
                    "原因": ["长事务阻塞", "表锁冲突", "备份时间选择不当"],
                    "解决方案": [
                        "使用--single-transaction选项",
                        "调整备份时间窗口",
                        "优化长事务",
                        "使用物理备份",
                        "分表备份策略"
                    ],
                    "预防措施": ["事务监控", "锁监控", "备份时间优化"]
                }
            },
            "性能问题": {
                "备份速度慢": {
                    "症状": ["备份时间过长", "影响业务性能", "备份窗口不足"],
                    "原因": ["I/O瓶颈", "网络带宽限制", "压缩算法选择", "并发度不足"],
                    "解决方案": [
                        "使用SSD存储",
                        "增加网络带宽",
                        "优化压缩设置",
                        "增加并发线程",
                        "使用专用备份网络"
                    ],
                    "性能调优": {
                        "mysqldump": "--single-transaction --routines --triggers --quick",
                        "mydumper": "--threads=8 --compress --build-empty-files",
                        "xtrabackup": "--parallel=8 --compress --compress-threads=4"
                    }
                },
                "恢复速度慢": {
                    "症状": ["恢复时间过长", "RTO目标无法达成", "业务中断时间长"],
                    "原因": ["备份文件过大", "索引重建慢", "I/O性能不足"],
                    "解决方案": [
                        "使用物理备份",
                        "优化硬件配置",
                        "并行恢复",
                        "预热缓存",
                        "分阶段恢复"
                    ]
                }
            },
            "数据一致性问题": {
                "备份数据不一致": {
                    "症状": ["外键约束错误", "数据校验失败", "应用程序错误"],
                    "原因": ["多表备份时间差", "事务未提交", "复制延迟"],
                    "解决方案": [
                        "使用事务一致性备份",
                        "停止写入操作",
                        "使用FLUSH TABLES WITH READ LOCK",
                        "验证备份一致性",
                        "使用物理备份"
                    ]
                },
                "增量备份链断裂": {
                    "症状": ["增量恢复失败", "binlog文件缺失", "LSN不连续"],
                    "原因": ["binlog清理过早", "备份文件丢失", "存储故障"],
                    "解决方案": [
                        "调整binlog保留时间",
                        "验证备份完整性",
                        "实施冗余存储",
                        "重新建立备份链",
                        "使用备份验证工具"
                    ]
                }
            }
        }
        
        self.diagnostic_tools = {
            "系统诊断": {
                "磁盘空间": "df -h",
                "磁盘I/O": "iostat -x 1",
                "网络连接": "netstat -an | grep 3306",
                "进程状态": "ps aux | grep mysql",
                "内存使用": "free -h"
            },
            "MySQL诊断": {
                "连接状态": "SHOW PROCESSLIST",
                "锁状态": "SHOW ENGINE INNODB STATUS",
                "复制状态": "SHOW SLAVE STATUS",
                "变量检查": "SHOW VARIABLES LIKE '%backup%'",
                "错误日志": "查看MySQL错误日志文件"
            },
            "备份工具诊断": {
                "mysqldump": "mysqldump --help",
                "mydumper": "mydumper --help",
                "xtrabackup": "xtrabackup --help",
                "日志分析": "分析备份工具输出日志"
            }
        }
    
    def show_common_issues(self):
        """显示常见问题"""
        print("常见备份问题与解决方案:")
        print("=" * 60)
        
        for category, issues in self.common_issues.items():
            print(f"\n{category}:")
            for issue, details in issues.items():
                print(f"\n  {issue}:")
                
                if '症状' in details:
                    print(f"    症状: {', '.join(details['症状'])}")
                if '原因' in details:
                    print(f"    原因: {', '.join(details['原因'])}")
                if '解决方案' in details:
                    print(f"    解决方案:")
                    for solution in details['解决方案']:
                        print(f"      • {solution}")
                if '预防措施' in details:
                    print(f"    预防措施: {', '.join(details['预防措施'])}")
                if '性能调优' in details:
                    print(f"    性能调优:")
                    for tool, params in details['性能调优'].items():
                        print(f"      {tool}: {params}")
    
    def show_diagnostic_tools(self):
        """显示诊断工具"""
        print("\n诊断工具和命令:")
        print("=" * 50)
        
        for category, tools in self.diagnostic_tools.items():
            print(f"\n{category}:")
            for tool, command in tools.items():
                print(f"  {tool}: {command}")
    
    def troubleshooting_workflow(self):
        """故障排除流程"""
        workflow = """
备份故障排除流程:

## 1. 问题识别阶段
1. 收集错误信息
   - 查看备份日志
   - 检查系统日志
   - 收集错误截图
   - 记录问题发生时间

2. 环境检查
   - 检查系统资源(CPU、内存、磁盘、网络)
   - 验证MySQL服务状态
   - 检查备份工具版本
   - 确认配置文件设置

## 2. 问题分析阶段
1. 错误分类
   - 系统级错误(资源不足、权限问题)
   - 网络级错误(连接超时、传输中断)
   - 应用级错误(SQL错误、工具bug)
   - 数据级错误(一致性问题、损坏)

2. 根因分析
   - 使用诊断工具收集信息
   - 分析错误日志和系统日志
   - 检查相关配置和权限
   - 验证网络连通性

## 3. 解决方案实施
1. 临时解决方案
   - 快速恢复备份功能
   - 使用替代备份方法
   - 调整备份参数
   - 释放系统资源

2. 永久解决方案
   - 修复根本原因
   - 优化系统配置
   - 更新备份策略
   - 加强监控和告警

## 4. 验证和测试
1. 功能验证
   - 执行测试备份
   - 验证备份完整性
   - 测试恢复功能
   - 检查监控告警

2. 性能验证
   - 测试备份速度
   - 验证系统影响
   - 检查资源使用
   - 确认RTO/RPO目标

## 5. 文档和改进
1. 问题记录
   - 更新故障知识库
   - 记录解决步骤
   - 分享经验教训
   - 更新操作手册

2. 流程改进
   - 优化备份流程
   - 加强预防措施
   - 改进监控机制
   - 更新应急预案
"""
        
        print("\n故障排除流程:")
        print("=" * 50)
        print(workflow)

# 故障排除演示
backup_troubleshooting_demo = BackupTroubleshooting()
backup_troubleshooting_demo.show_common_issues()
backup_troubleshooting_demo.show_diagnostic_tools()
backup_troubleshooting_demo.troubleshooting_workflow()

7.6 总结

通过本章的学习,我们全面了解了MySQL备份与恢复的各个方面:

核心要点回顾

  1. 备份策略设计

    • 理解不同备份类型的特点和适用场景
    • 掌握3-2-1备份原则和分层备份策略
    • 学会根据RTO/RPO要求制定备份计划
  2. 备份工具掌握

    • mysqldump:逻辑备份的标准工具
    • mydumper:高性能并行备份工具
    • Percona XtraBackup:物理备份的首选工具
    • 各工具的优缺点和适用场景
  3. 恢复技术实践

    • 完全恢复、增量恢复、时间点恢复
    • 不同场景下的恢复策略选择
    • 恢复测试和验证的重要性
  4. 监控与验证

    • 备份监控指标和告警规则
    • 备份完整性验证方法
    • 自动化测试和验证流程
  5. 最佳实践应用

    • 备份策略的设计原则
    • 自动化和智能化管理
    • 安全和合规考虑
    • 常见问题的预防和解决

实施建议

  1. 循序渐进:从简单的备份策略开始,逐步完善和优化
  2. 测试验证:定期进行恢复测试,确保备份的可用性
  3. 监控告警:建立完善的监控体系,及时发现和处理问题
  4. 文档管理:维护详细的备份和恢复文档,便于团队协作
  5. 持续改进:根据业务发展和技术演进,不断优化备份策略

下一步学习

在掌握了MySQL备份与恢复的基础知识后,建议继续学习: - MySQL集群和分布式架构的备份策略 - 云环境下的备份和灾难恢复 - 大数据量场景下的备份优化 - 备份数据的合规性管理

下一章我们将学习MySQL安全与权限管理,了解如何保护MySQL数据库的安全,包括用户管理、权限控制、数据加密、审计日志等重要内容。