Python实现MySQL全量数据同步的实用脚本
本文详解如何使用 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数据迁移与自动化运维的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













