MySQL主从切换自动化用例设计

设计MySQL主从切换的自动化测试用例,核心是将“切换触发、业务模拟、状态监控、数据校验”全流程自动化,覆盖正常、异常、边界场景,同时确保测试可重复、结果可量化。以下是基于“场景驱动+工具链集成”的自动化测试方案设计。

一、自动化测试框架与工具链选型

自动化测试需解决“环境快速重建、操作自动化、校验标准化”三大问题,推荐工具链如下:

环节 工具/技术 作用
测试框架 Python + pytest 管理测试用例、断言结果、生成报告
数据库操作 pymysql / SQLAlchemy 自动执行SQL(如查询主从状态、写入测试数据)
主从环境部署 Docker + docker-compose 快速拉起主从架构(1主2从),支持环境重置(每次测试前初始化)
切换触发工具 自定义Shell脚本 + MHA 手动切换(执行SQL命令)或自动切换(调用MHA的masterha_manager)
数据一致性校验 自定义校验脚本 + pt-table-checksum 自动计算表checksum、对比行数、校验特殊对象(视图/存储过程)
业务模拟 多线程写入脚本 模拟并发业务写入(INSERT/UPDATE/DELETE),生成可追溯的测试数据
监控与日志 日志模块(logging) + Prometheus 记录切换耗时、同步延迟等指标,收集异常日志

二、核心测试场景与自动化用例设计

按“基础功能→复杂场景→异常容错”的层级覆盖,每个用例包含“前置条件→执行步骤→预期结果”三要素,通过代码实现全流程自动化。

场景1:正常切换(无业务写入时)

测试目标:验证无增量数据时,切换后新主库与原主库数据完全一致,业务可正常读写。

自动化步骤 技术实现细节
1. 环境初始化:用Docker启动1主2从架构,初始化测试数据(含5张表,覆盖int/varchar/blob等类型,含主键/外键) 编写docker-compose.yml定义主从配置(如server-id、binlog开启),启动后执行init_data.sql自动生成测试数据
2. 检查主从同步状态:确认所有从库Seconds_Behind_Master=0Slave_IO/SQL_Running=Yes 用pymysql连接从库,执行show slave status\G,解析结果并断言同步正常
3. 暂停业务写入:通过API关闭模拟写入脚本(确保切换期间无新数据) 调用写入脚本的停止接口(如HTTP请求),或设置全局变量is_writing=False
4. 自动触发切换:选择从库1作为新主库,执行切换命令(stop slave; reset slave all; 编写Python函数trigger_switch(new_master_ip),通过SSH执行切换SQL命令
5. 切换业务连接:修改测试客户端的数据库连接地址为新主库IP 调用配置中心API(如Nacos)更新连接参数,或直接修改测试脚本的db_config
6. 校验数据一致性:
① 对比新主库与原主库所有表的行数
② 计算表的MD5校验和(忽略自增ID顺序)
③ 校验视图、存储过程定义是否一致
① 执行select count(*) from 表名对比行数
② 用checksum table 表名计算校验和
③ 查询information_schema.VIEWS对比视图定义
7. 校验业务可用性:在新主库执行100条随机读写操作(INSERT/SELECT),确认无报错 生成随机SQL(如INSERT INTO test (col) VALUES (随机值)),执行后断言无异常

场景2:有增量写入时的切换

测试目标:验证切换过程中持续写入的增量数据,在新主库中完整可见,无丢失/重复。

自动化步骤 技术实现细节
1. 环境初始化:同场景1,额外启动“并发写入脚本”(10个线程,每秒共写入100条数据,每条数据含create_time=当前时间戳 用Python的threading模块实现并发写入,每条数据记录唯一标识(如uuid())以便追溯
2. 记录切换前的基准点:
① 原主库的binlog位置(show master status
② 写入脚本的“切换前最后一条数据ID”
用变量pre_switch_binlog_pos记录binlog位置,pre_switch_last_id记录最后写入的uuid
3. 触发切换:在写入脚本运行中,执行场景1的切换步骤4-5(不暂停写入) 切换过程中,写入脚本持续生成数据(记录switch_start_timeswitch_end_time
4. 校验增量数据完整性:
① 统计切换期间(switch_start_timeswitch_end_time)写入的总条数
② 在新主库中查询该时间段的记录数,确认相等
③ 随机抽取10%的记录,对比内容是否一致
① 从写入脚本的日志中统计增量总条数(total_increment
② 新主库执行select count(*) from test where create_time between ...
③ 用select * from test where uuid in (随机抽取的ID列表)对比内容
5. 校验大事务一致性:切换前启动一个未提交的大事务(插入1万行数据),切换过程中提交,验证新主库是否完整同步 begin; INSERT ...开启事务,切换开始后执行commit;,新主库查询该表行数是否+1万

场景3:异常场景切换(主库宕机)

测试目标:验证主库突然宕机时,自动切换工具(如MHA)能正确触发切换,且数据丢失量在可接受范围(如≤1秒)。

自动化步骤 技术实现细节
1. 环境初始化:部署主从架构+MHA(Manager+Node),配置自动切换参数(如检测间隔3秒,失败阈值2次) 用Docker部署MHA,修改masterha_default.cnf配置故障检测参数
2. 启动持续写入:同场景2,记录每条数据的写入时间戳 写入数据含write_timestamp=UNIX_TIMESTAMP()
3. 模拟主库宕机:执行docker stop 主库容器kill -9 主库进程ID 用Python的subprocess模块执行系统命令,强制终止主库
4. 监控MHA自动切换:通过MHA的日志(/var/log/masterha/)确认切换触发,记录切换耗时(switch_duration = 切换完成时间 - 主库宕机时间 tail -f监控MHA日志,匹配“Master switched to ...”关键字,计算耗时
5. 校验数据丢失量:
① 找到主库宕机前最后一条成功写入的记录(max(write_timestamp)
② 新主库中找到最早未同步的记录(min(write_timestamp)
③ 计算时间差(data_loss = 未同步记录时间 - 最后同步记录时间
原主库重启后(可选)查询最后写入记录,新主库查询同步的最大时间戳,计算差值
6. 校验新主从架构:确认其他从库(含旧主库修复后)已指向新主库,同步正常 登录其他从库执行show slave status\G,断言Master_Host为新主库IP,同步状态正常

三、自动化校验核心方法(代码示例)

1. 主从同步状态校验

import pymysql
from pymysql.cursors import DictCursor

def check_slave_status(slave_ip, port=3306, user="root", password="123456"):
    """检查从库同步状态,返回是否正常"""
    conn = pymysql.connect(host=slave_ip, port=port, user=user, password=password, cursorclass=DictCursor)
    with conn.cursor() as cursor:
        cursor.execute("show slave status")
        slave_status = cursor.fetchone()
        if not slave_status:
            return False, "未配置从库"
        # 校验IO线程和SQL线程是否运行,延迟是否为0
        io_running = slave_status["Slave_IO_Running"] == "Yes"
        sql_running = slave_status["Slave_SQL_Running"] == "Yes"
        delay = slave_status["Seconds_Behind_Master"] == 0
        conn.close()
        return (io_running and sql_running and delay), f"IO: {io_running}, SQL: {sql_running}, Delay: {delay}"

2. 数据一致性校验(表checksum对比)

def calculate_table_checksum(db_ip, table_name):
    """计算表的checksum"""
    conn = pymysql.connect(host=db_ip, user="root", password="123456")
    with conn.cursor() as cursor:
        cursor.execute(f"checksum table {table_name}")
        checksum = cursor.fetchone()[1]  # checksum结果在第二列
    conn.close()
    return checksum

def verify_data_consistency(old_master_ip, new_master_ip, tables):
    """对比新旧主库的表checksum"""
    for table in tables:
        old_checksum = calculate_table_checksum(old_master_ip, table)
        new_checksum = calculate_table_checksum(new_master_ip, table)
        assert old_checksum == new_checksum, f"表{table}数据不一致:旧主{old_checksum} vs 新主{new_checksum}"

3. 模拟并发写入

import threading
import time
import uuid

def concurrent_writer(db_ip, table_name, duration=60):
    """持续写入数据,duration秒后停止"""
    conn = pymysql.connect(host=db_ip, user="root", password="123456", db="test")
    start_time = time.time()
    while time.time() - start_time < duration:
        try:
            data_id = str(uuid.uuid4())
            create_time = time.strftime('%Y-%m-%d %H:%M:%S')
            with conn.cursor() as cursor:
                cursor.execute(f"INSERT INTO {table_name} (data_id, create_time) VALUES (%s, %s)", (data_id, create_time))
                conn.commit()
            print(f"写入成功:{data_id}")
            time.sleep(0.01)  # 控制写入频率
        except Exception as e:
            print(f"写入失败:{e}")
            conn.rollback()
    conn.close()

# 启动10个写入线程,持续30秒
for _ in range(10):
    t = threading.Thread(target=concurrent_writer, args=("原主库IP", "test_table", 30))
    t.start()

四、测试结果与报告自动化

  • 核心指标收集:切换耗时(从触发到业务恢复)、数据丢失量(异常场景)、数据一致性结果(通过/失败)、业务中断时间。
  • 报告生成:用pytest-html生成HTML报告,包含每个场景的步骤、截图(如主从状态截图)、日志片段。
  • 告警机制:测试失败时(如数据不一致),通过邮件或企业微信通知测试人员,附带详细日志。

五、环境清理与复用

自动化测试后需快速重置环境,确保下次测试无干扰:

  1. 停止所有容器,删除数据卷(docker-compose down -v);
  2. 重新启动容器,执行初始化脚本(自动创建主从、导入测试数据);
  3. 记录环境重置耗时(目标≤5分钟),确保测试效率。

总结

MySQL主从切换的自动化测试需围绕“场景全覆盖+执行无人工干预+校验可量化”设计,核心是通过代码将“环境准备-切换触发-数据校验”串联,结合Docker实现环境一致性,用多线程模拟真实业务压力,最终通过自动化工具链输出可靠的切换质量指标(如数据零丢失、切换耗时<30秒)。这种方案既能提升测试效率(支持每日定时执行),又能避免人工操作的疏漏,更贴近生产环境的真实场景。

posted @ 2025-08-01 18:42  程煕  阅读(28)  评论(0)    收藏  举报