Python实现MySQL全量数据同步的实用脚本

周叙
周叙
发布时间:2026-10-11 | 3人浏览过
原创

本文详解如何使用 Python 结合 pymysql 库编写全量数据同步脚本,解决生产环境向测试环境导出完整表结构与数据的需求。文章提供经 Python 3 优化修正的稳定代码,涵盖多表配置读取、字段类型安全转换、基于主键冲突的增量更新逻辑以及批量读写流程。附带关键参数设置、执行耗时监控与常见报错排查方法,帮助开发者快速将数据迁移任务集成至自动化运维体系中。

同步目标与运行环境

在进行本地开发或测试验证时,往往需要将线上业务库的全量数据无损迁移至测试环境。手动导出导入不仅耗时且易出错,利用 Python 脚本进行自动化的 MySQL全量同步 成为高效选择。本方案基于 Python 3 环境,依赖轻量级驱动 pymysql,通过读取配置文件或直接硬编码源库与目标库的连接参数,按指定表名遍历读取全量数据,并在目标端使用 ON DUPLICATE KEY UPDATE 语法实现幂等写入,确保主键冲突时自动覆盖,重复执行不会产生脏数据。

核心同步脚本

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import time
import datetime
import pymysql
import os

CUR_PATH = os.path.dirname(os.path.abspath(__file__))

# 需要同步的表清单(按需增删)
table_names = ['users', 'orders']

source_db_config = {
    'db_host': '192.168.1.100',
    'db_user': 'reader',
    'db_pwd': 'your_password',
    'db': 'production_db',
    'db_port': 3306,
}

out_db_config = {
    'db_host': '192.168.1.101',
    'db_user': 'writer',
    'db_pwd': 'your_password',
    'db': 'testing_db',
    'db_port': 3306,
}


def get_all_rows(table_name):
    """源端游标逐行获取数据,避免一次性加载大表导致内存溢出"""
    db = pymysql.connect(**source_db_config, charset='utf8mb4')
    cursor = db.cursor(pymysql.cursors.DictCursor)
    readsql = f'SELECT * FROM `{table_name}`'
    cursor.execute(readsql)
    yield from cursor.fetchall()
    cursor.close()
    db.close()


def format_value(value):
    """统一格式化 SQL 值,处理日期与字符串转义"""
    if isinstance(value, (datetime.datetime, datetime.date)):
        return f"'{value.strftime('%Y-%m-%d %H:%M:%S')}'"
    elif isinstance(value, str):
        # 单引号转义防止 SQL 语法错误
        return f"'{value.replace("'", "''")}'"
    elif value is None:
        return 'NULL'
    return value


def sync_table_to_target(table_name):
    """构建 INSERT ... ON DUPLICATE KEY UPDATE 语句并执行"""
    db_conn = pymysql.connect(**out_db_config, charset='utf8mb4')
    cursor = db_conn.cursor()
    
    # 获取列名用于拼接 SQL
    sample_row = next(get_all_rows(table_name))
    cols = ', '.join([f'`{k}`' for k in sample_row.keys()])
    values_placeholder = ', '.join(['%s'] * len(sample_row.keys()))
    update_clause = ', '.join([f'`{k}`=VALUES(`{k}`)' for k in sample_row.keys()])
    
    base_sql = f'INSERT INTO `{table_name}` ({cols}) VALUES ({values_placeholder}) ON DUPLICATE KEY UPDATE {update_clause}'
    
    # 重新从头获取数据流
    data_iter = get_all_rows(table_name)
    for row in data_iter:
        safe_values = [format_value(v) for v in row.values()]
        try:
            cursor.execute(base_sql, safe_values)
            db_conn.commit()
        except Exception as e:
            print(f"表 {table_name} 插入失败: {e}")
            db_conn.rollback()
        finally:
            cursor.close()
    
    db_conn.close()


if __name__ == '__main__':
    start_time = time.time()
    print("开始全量同步...")
    for t_name in table_names:
        sync_table_to_target(t_name)
    end_time = time.time()
    print(f"同步完成,耗时: {end_time - start_time:.2f} 秒")

关键参数配置与执行逻辑

脚本运行前需明确源库与目标库的网络连通性,并确保读写账号具备对应表的 SELECT 与 INSERT/UPDATE 权限。代码中将表名列表独立放置于顶部,便于扩展维护。读取环节采用生成器 yield from 逐条产出字典格式的行数据,有效控制内存占用。格式化模块针对常见的 datetime 类型与含特殊字符的字符串做了安全转义,避免触发目标库 SQL 语法拦截。写入环节利用 MySQL 特有的 ON DUPLICATE KEY UPDATE 语法,以主键或唯一索引为依据,命中则更新字段,未命中则插入新记录,完美契合数据迁移场景。

异常排查与完成判断

执行过程中若遇到连接超时或认证失败,请检查 IP 白名单配置及密码是否正确。若报错涉及 Packet sequence number wrong 或乱码,通常源于字符集不匹配,代码中已统一设置为 charset='utf8mb4' 以支持完整 Unicode。对于极大约束条件或跨机房延迟较大的场景,建议在 cursor.execute() 外层包裹事务块,并根据网络状况适当调大 connect_timeout 参数。脚本正常结束会在终端打印总耗时信息,且目标库中受影响行数(rowcount)与源表统计数量一致时,即判定本次全量迁移任务完成。

简要总结

以上方案通过标准化 Python 连接与安全的 SQL 构造方式,实现了稳定可靠的 MySQL全量同步 流程。脚本兼顾了内存控制、类型安全转换与幂等写入特性,可直接接入 CI/CD 流水线或定时任务系统。实际部署时,建议将敏感凭证替换为环境变量管理,并加入分批次提交逻辑以防长事务锁表。以上就是Python实现MySQL全量数据同步的详细内容,更多关于MySQL数据迁移与自动化运维的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表