一、命令行工具
1. mysqldump
- 功能:导出表结构和数据为 SQL 文件,支持全量或按条件导出(如历史数据)。
- 常用命令:
# 导出单表历史数据(按时间筛选) mysqldump -u 用户名 -p 数据库名 表名 --where="创建时间<'2023-01-01'" > history_data.sql # 导出整个数据库 mysqldump -u 用户名 -p 数据库名 > full_backup.sql - 优势:简单通用,支持跨服务器迁移(通过文件传输)。
- 局限:大表导出效率较低,需配合定时任务实现增量迁移
2. mysqlpump
- 功能:并行导出数据,效率高于
mysqldump,适合大表迁移。 - 命令示例:
mysqlpump -u 用户名 -p 数据库名 > parallel_backup.sql - 优势:支持并行处理,缩短导出时间
二、专用迁移工具
1. pt-archiver(Percona Toolkit)
- 功能:支持按时间、主键等条件筛选历史数据,实现增量归档,避免锁表。
- 核心命令:
pt-archiver --source="h=源库地址,D=库名,t=表名" \ --dest="h=目标库地址,D=归档库名,t=归档表名" \ --where="创建时间<'2023-01-01'" \ --limit=1000 --commit-each - 优势:支持断点续传、事务安全,适合大规模历史数据迁移
2. DataX
- 功能:阿里开源的 ETL 工具,支持 MySQL 到 MySQL、MySQL 到其他数据库的增量/全量同步。
- 配置示例:
{ "job": { "content": [ { "reader": { "name": "mysqlreader", "parameter": { "username": "用户", "password": "密码", "column": ["*"], "where": "创建时间<'2023-01-01'", "splitPk": "主键ID" } }, "writer": { "name": "mysqlwriter", "parameter": { "username": "用户", "password": "密码", "table": "归档表名" } } } ] } } - 优势:支持多种数据源,可配置复杂同步逻辑(如过滤、转换)
三、图形化工具
1. MySQL Workbench
- 操作步骤:
- 连接源库和目标库,进入 Server → Data Export。
- 选择需导出的表,设置导出格式(SQL/CSV)和条件(如时间范围)。
- 点击 Start Export 完成迁移。
- 优势:可视化操作,适合新手和不熟悉命令行的用户
2. Navicat
- 功能:支持跨数据库迁移,可实时同步或定时导出历史数据。
- 操作:
- 右键表 → 导出向导 → 选择目标库和过滤条件(如
WHERE 日期<'2023-01-01')。 - 支持通过 SSH 隧道连接远程服务器
- 右键表 → 导出向导 → 选择目标库和过滤条件(如
四、选择建议
- 小规模/一次性迁移:用
mysqldump或 MySQL Workbench,简单直接。 - 大规模/实时迁移:选
pt-archiver或 DataX,支持增量同步和高效处理。 - 跨数据库/复杂场景:DataX 或 ETL 工具,适配多种数据源和转换需求。
注意事项:
- 迁移前需备份原数据,避免丢失。
- 大表建议分批导出,或通过
LIMIT和OFFSET分段处理 - 确保目标库字符集、引擎与源库一致,避免数据异常
大表历史数据迁移方案(同库归档)
一、推荐方案
使用 pt-archiver 工具分批迁移数据,避免锁表影响业务
操作步骤
-
创建归档表
CREATE TABLE 原表名_history LIKE 原表名; -
使用pt-archiver迁移数据
pt-archiver --source="h=localhost,D=数据库名,t=原表名" \ --dest="h=localhost,D=数据库名,t=原表名_history" \ --where="创建时间<'2025-01-01'" \ # 按时间筛选历史数据 --limit=5000 --commit-each --no-delete # 每次处理5000条,不删除原表数据 -
验证数据一致性
-- 检查原表数据量是否减少 SELECT COUNT(*) FROM 原表名 WHERE 创建时间<'2025-01-01'; -- 检查归档表数据量是否正确 SELECT COUNT(*) FROM 原表名_history WHERE 创建时间<'2025-01-01';
二、关键注意事项
-
分批处理
- 通过
--limit参数控制每次迁移的数据量(建议5000-10000条),避免大事务阻塞业务 - 可设置
--sleep参数(如--sleep=1),在批次间暂停1秒,降低对主库压力。
- 通过
-
避免锁表
- 使用
--no-delete参数仅迁移数据,不删除原表记录,减少锁表风险 - 若需删除原表数据,建议在业务低峰期执行,并先备份数据。
- 使用
-
索引优化
- 确保归档表有与原表相同的索引,提升查询效率
-
监控与回滚
- 迁移过程中监控数据库性能(如CPU、I/O、锁等待)。
- 若出现异常,可通过
--abort参数终止迁移,并检查数据一致性。
三、替代方案(无工具场景)
若无法使用pt-archiver,可采用以下手动方式:
-
分批次INSERT+DELETE
-- 第一步:插入历史数据到归档表 INSERT INTO 原表名_history SELECT * FROM 原表名 WHERE 创建时间<'2025-01-01' LIMIT 5000; -- 第二步:删除原表中的已迁移数据 DELETE FROM 原表名 WHERE 创建时间<'2025-01-01' LIMIT 5000; -- 重复执行以上两步,直到数据迁移完成 -
使用事务控制
START TRANSACTION; -- 执行INSERT和DELETE操作 COMMIT;注意:大事务仍可能导致锁表,建议分批提交。
若无法使用 pt-archiver,可通过 分批次 INSERT + DELETE 手动实现数据迁移,以下是具体方案及优化要点:
一、核心实现逻辑
通过 循环分批 处理数据,每次迁移一小部分记录,避免大事务锁表。
关键步骤:
- 分批次查询数据:用
LIMIT限制每次迁移的行数(如 5000 条)。 - 插入归档表:将查询结果批量插入目标表。
- 删除原表数据:删除已迁移的记录,确保数据一致性。
- 循环执行:重复上述步骤,直到所有数据迁移完成。
二、SQL 实现示例
1. 基础分批迁移(无事务)
-- 假设需迁移原表中 `created_at < '2025-01-01'` 的数据,每次处理 5000 条 SET @batch_size = 5000; -- 每批次处理的数据量 SET @rows_affected = 1; -- 初始化受影响行数,用于循环控制 WHILE @rows_affected > 0 DO -- 1. 插入数据到归档表 INSERT INTO 原表名_history SELECT * FROM 原表名 WHERE created_at < '2025-01-01' LIMIT @batch_size; -- 2. 删除原表中的已迁移数据 DELETE FROM 原表名 WHERE created_at < '2025-01-01' LIMIT @batch_size; -- 3. 获取本次受影响的行数,用于判断是否继续循环 SET @rows_affected = ROW_COUNT(); END WHILE;
说明:
ROW_COUNT()返回上一条 SQL 语句影响的行数,若为 0 则表示无数据可迁移,循环结束。- 适用于小规模数据迁移,但大表可能因长时间运行导致锁表风险。
2. 优化版本(带事务+错误处理)
-- 开启事务(确保批量操作的原子性) START TRANSACTION; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN -- 发生错误时回滚事务 ROLLBACK; SELECT '迁移失败,已回滚' AS message; END; -- 分批次处理数据 SET @batch_size = 5000; SET @rows_affected = 1; WHILE @rows_affected > 0 DO -- 插入数据 INSERT INTO 原表名_history SELECT * FROM 原表名 WHERE created_at < '2025-01-01' LIMIT @batch_size; -- 删除数据 DELETE FROM 原表名 WHERE created_at < '2025-01-01' LIMIT @batch_size; -- 提交事务(每批次提交一次,减少锁表时间) COMMIT; -- 重新开启事务,处理下一批次 START TRANSACTION; SET @rows_affected = ROW_COUNT(); -- 需重新获取受影响行数 END WHILE; -- 最终提交(确保所有批次成功后提交) COMMIT;
优化点:
- 事务控制:每批次提交一次事务,避免长时间持有锁。
- 错误处理:通过
DECLARE EXIT HANDLER捕获异常,确保失败时回滚。
三、进阶优化技巧
1. 按主键分批(避免全表扫描)
若表有自增主键,可按主键范围分批,提升查询效率:
-- 假设主键为 `id`,先查询最大主键值 SET @max_id = (SELECT MAX(id) FROM 原表名); SET @min_id = 0; SET @batch_size = 5000; WHILE @min_id < @max_id DO INSERT INTO 原表名_history SELECT * FROM 原表名 WHERE id BETWEEN @min_id AND @min_id + @batch_size - 1 AND created_at < '2025-01-01'; DELETE FROM 原表名 WHERE id BETWEEN @min_id AND @min_id + @batch_size - 1 AND created_at < '2025-01-01'; SET @min_id = @min_id + @batch_size; END WHILE;
优势:通过主键范围快速定位数据,减少全表扫描开销。
2. 禁用索引(提升插入速度)
若归档表无复杂索引,可临时禁用索引,迁移完成后再重建:
-- 禁用索引(InnoDB 支持) ALTER TABLE 原表名_history DISABLE KEYS; -- 执行批量插入和删除操作... -- 重建索引 ALTER TABLE 原表名_history ENABLE KEYS;
注意:仅适用于非唯一索引,且需确保数据一致性。
四、注意事项
- 监控性能:
- 使用
SHOW PROCESSLIST查看数据库负载,避免长时间占用连接。 - 大表建议在低峰期执行,减少对业务的影响。
- 使用
- 备份数据:
- 迁移前先备份原表(如
mysqldump),防止误操作导致数据丢失。
- 迁移前先备份原表(如
- 测试验证:
- 先在测试环境用小数据量验证逻辑,确认无误后再执行正式迁移。
五、替代方案(推荐)
若分批次操作复杂,可考虑 导出/导入文件(如 SELECT INTO OUTFILE + LOAD DATA INFILE),速度更快且减少锁表风险
导出/导入文件方案(SELECT INTO OUTFILE + LOAD DATA INFILE)
核心逻辑:将原表数据导出为文件,再导入到归档表,避免直接操作原表导致锁表。
一、导出数据到文件
使用 SELECT INTO OUTFILE 将原表中需归档的数据导出为CSV文件(支持自定义分隔符、字段包围符等)。
示例:
-- 导出原表中创建时间早于2025-01-01的数据到CSV文件 SELECT * INTO OUTFILE '/tmp/history_data.csv' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM 原表名 WHERE created_at < '2025-01-01';
说明:
FIELDS TERMINATED BY ',':字段间以逗号分隔(可根据需求改为制表符\t等)。ENCLOSED BY '"':字符串字段用双引号包裹,避免特殊字符(如逗号)导致解析错误。- 路径限制:文件需导出到MySQL服务器本地目录(可通过
SHOW VARIABLES LIKE 'secure_file_priv'查看允许的路径)
二、导入文件到归档表
使用 LOAD DATA INFILE 将导出的CSV文件快速导入到归档表。
示例:
-- 导入CSV文件到归档表(假设表结构与原表一致) LOAD DATA INFILE '/tmp/history_data.csv' INTO TABLE 原表名_history FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n';
说明:
- 若归档表需额外字段(如归档时间),可在导入后通过
UPDATE语句补充。 - 支持大文件快速导入,避免逐行插入的性能问题
三、完整流程(含清理)
- 创建归档表(若不存在):
CREATE TABLE 原表名_history LIKE 原表名; - 导出数据:
SELECT * INTO OUTFILE '/tmp/history_data.csv' FIELDS TERMINATED BY ',' FROM 原表名 WHERE created_at < '2025-01-01'; - 导入数据:
LOAD DATA INFILE '/tmp/history_data.csv' INTO TABLE 原表名_history; - 验证数据:
-- 检查原表数据是否减少 SELECT COUNT(*) FROM 原表名 WHERE created_at < '2025-01-01'; -- 检查归档表数据是否正确 SELECT COUNT(*) FROM 原表名_history WHERE created_at < '2025-01-01'; - 清理临时文件(可选):
rm /tmp/history_data.csv # 导入完成后删除文件
四、优势与注意事项
- 优势:
- 无锁表风险:导出/导入过程不涉及原表更新操作,避免锁表影响业务。
- 高效:基于文件批量操作,速度远快于逐行SQL语句
- 注意事项:
- 权限:确保MySQL用户有文件读写权限(
SELECT INTO OUTFILE需FILE权限) - 路径配置:通过
secure_file_priv参数限制文件路径,避免安全风险 - 数据一致性:导入前需确认文件内容与表结构匹配,可先在小数据量下测试。
- 权限:确保MySQL用户有文件读写权限(
最后修改时间:2025-08-07 09:54:54
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




