mysql从旧服务器迁移到新服务器_mysql全量迁移步骤

8次阅读

mysqldump导出必须加–single-transaction和–routines:前者保证InnoDB一致性快照,后者导出存储过程、函数、触发器;推荐命令含–triggers、–events、–hex-blob及utf8mb4字符集显式指定。

mysql从旧服务器迁移到新服务器_mysql全量迁移步骤

mysqldump 导出时必须加 --single-transaction--routines

不加 --single-transaction,在有写入的旧库上导出可能产生不一致快照,尤其对 InnoDB 表;而 --routines 是为了导出存储过程、函数、触发器——这些默认不被包含。如果业务依赖自定义函数或定时触发逻辑,漏掉会导致新库功能异常。

推荐导出命令:

mysqldump -h old_host -u user -p --single-transaction --routines --triggers --events --hex-blob --default-character-set=utf8mb4 database_name > dump.sql
  • --triggers--events 显式加上,避免因 MySQL 版本差异导致默认行为变化
  • --hex-blob 防止二进制字段(如 VARBINARYBLOB)在导出时被错误转义
  • 务必确认旧库字符集是 utf8mb4,否则导出文件里中文可能乱码,导入后变成问号或截断

导入前要在新服务器上创建同名数据库并指定 utf8mb4 字符集

直接 CREATE database db_name;继承 MySQL 实例默认字符集,而很多老服务器默认还是 latin1utf8(即 utf8mb3)。一旦库级字符集不对,即使 dump.sql 里声明了 CHARSET=utf8mb4,表和列仍可能建错。

安全做法是显式指定:

CREATE DATABASE `database_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
  • 导入前执行 SET NAMES utf8mb4;,确保客户端连接使用正确编码
  • 如果导入报错 Error 1366 (HY000): Incorrect String value,大概率是某张表的列没继承库级字符集,需检查 dump.sqlCREATE table 语句是否含 CHARSET=utf8mb4
  • 不要依赖 my.cnf 的全局设置来“一劳永逸”,迁移过程必须显式控制

导入大文件时禁用唯一性检查和自动提交能提速 5–10 倍

默认导入会逐条插入并校验唯一索引、外键,还频繁刷盘。对于百万级以上数据,这会让导入从几分钟拖到几小时。

dump.sql 开头手动插入三行(或用 sed 预处理):

SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0; SET AUTOCOMMIT=0;

并在结尾补上:

SET UNIQUE_CHECKS=1; SET FOREIGN_KEY_CHECKS=1; COMMIT;
  • 跳过唯一性检查只在确认源数据本身无重复的前提下才安全
  • 关闭 AUTOCOMMIT 后,整个导入变成一个事务,内存压力增大,但 IO 减少显著;若中途失败,需重跑全量
  • 导入完成后务必手动执行 SHOW ENGINE INNODB STATUSG 查看是否有未释放的锁或长事务残留

迁移后必须验证 mysql.proc 表和 DEFINER 权限问题

存储过程/函数导出时会带 DEFINER=`user`@`host`,如果新库没有这个用户,或者用户权限不足,调用时会报 ERROR 1449 (HY000): The user specified as a definer does not exist

  • 导入后运行 select db, name, type, definer FROM mysql.proc WHERE db = 'database_name'; 检查所有对象definer
  • 批量修正:用 mysqldump--skip-definer 重新导出,或导入后执行 UPDATE mysql.proc SET definer='new_user@localhost' WHERE db='database_name';(注意操作前先 FLUSH TABLES
  • 别忘了 GRANT EXECUTE ON PROCEDURE 给应用账号,否则即使过程存在也无法调用

跨版本迁移(比如 5.7 → 8.0)时,mysql.proc 表结构已废弃,改用 information_schema.routines,此时必须用 mysqldump --routines 而不是直接拷表。

text=ZqhQzanResources