C++如何将本地MySQL表数据插入同步至远程MySQL数据库
现有两套MySQL实例,一套部署在本地客户端服务器,一套部署在独立远程机器,需要将本地数据库的表数据同步插入到远程数据库。使用C++基于MySQL C API开发时,发现mysql_query接口绑定传入的连接句柄执行操作,之前的实现仅创建了一个连接对象,仅能对接本地数据库,无法直接操作远程库,需要可行的解决方案。
维护双独立连接句柄,分别对接两个数据库实例
MySQL C API本身支持同一进程内创建多个独立连接句柄,不存在全局仅允许一个生效连接的限制,之前的限制来自仅初始化了一个MYSQL*连接对象。
实现逻辑非常直接:分别初始化两个连接句柄,调用mysql_real_connect分别对接本地库、远程库;读取本地数据时传入本地连接句柄执行查询,遍历拿到的结果集后,传入远程连接句柄执行写入操作即可。
基础实现参考:#include <mysql/mysql.h> #include <cstdio> int main() { // 初始化两个独立连接对象 MYSQL* local_conn = mysql_init(nullptr); MYSQL* remote_conn = mysql_init(nullptr); // 分别建立连接 mysql_real_connect(local_conn, "127.0.0.1", "local_account", "local_pwd", "local_db", 3306, nullptr, 0); mysql_real_connect(remote_conn, "远程数据库IP", "remote_account", "remote_pwd", "remote_db", 3306, nullptr, 0); // 关闭远程连接自动提交,开启事务提升批量写入性能 mysql_autocommit(remote_conn, 0); // 从本地库查询目标数据 mysql_query(local_conn, "SELECT id, name, create_time FROM DB.Table1"); MYSQL_RES* result = mysql_store_result(local_conn); MYSQL_ROW row; int batch_count = 0; // 遍历结果集写入远程库 while ((row = mysql_fetch_row(result)) != nullptr) { char insert_sql[2048]; // 生产环境建议使用预处理接口mysql_stmt_*系列,避免SQL注入、减少转义开销 snprintf(insert_sql, sizeof(insert_sql), "INSERT INTO target_table(id, name, create_time) VALUES (%s, '%s', '%s')", row[0], row[1], row[2]); mysql_query(remote_conn, insert_sql); batch_count++; // 每1000条提交一次事务,平衡性能和故障恢复成本 if (batch_count % 1000 == 0) { mysql_commit(remote_conn); } } // 提交最后一批剩余数据 mysql_commit(remote_conn); // 资源回收 mysql_free_result(result); mysql_close(local_conn); mysql_close(remote_conn); return 0; }大批量同步场景不要单条记录提交一次事务,否则性能会下降12个数量级,按照100010000条一批提交即可。
使用MySQL原生同步能力,剥离业务层同步逻辑
如果同步场景不需要业务层做额外数据加工,不需要在C++代码中实现同步逻辑,直接用MySQL自带能力即可:- 一次性全量同步场景:本地执行
mysqldump导出目标表结构和数据,直接通过管道导入远程库,不需要编写额外代码 - 长期固定表同步场景:可以配置MySQL主从复制,将本地库设为主库,远程库设为从库,配置仅同步目标表的复制规则,由MySQL自身完成全量、增量同步,业务层无感知
- 偶发触发同步场景:在远程库开启FEDERATED引擎,创建映射本地目标表的联邦表,业务代码仅需要连接远程库,执行
INSERT INTO 本地目标表 SELECT * FROM 联邦表即可完成数据拉取,不需要维护双连接。
- 一次性全量同步场景:本地执行
使用封装好的C++ MySQL客户端降低开发成本
如果觉得原生C API操作繁琐、容易出现资源泄漏,可以使用官方提供的MySQL Connector/C或者其他成熟的轻量C MySQL封装库,这类库通常支持连接管理、预处理语句、结果集自动回收,你只需要创建两个独立连接实例分别指向本地、远程库,调用对应封装的查询、写入接口即可,大幅减少样板代码量。
注意:不要尝试复用单个
MYSQL*句柄反复断开重连切换目标库,频繁建连的开销远高于维护两个长连接的成本,还容易出现连接状态残留、事务错乱的问题。
内容的提问来源于stack exchange,提问作者Ali

