加 --no-create-db 参数可避免 create database 报错,因其跳过建库及 use 语句;再配合 --skip-triggers、--skip-routines、--skip-events 精确导出表结构,并用 sed 替换库名适配目标库。
mysqldump 跨库同步结构时,为什么 create database 语句总报错?
MySQL 默认导出包含 CREATE DATABASE 和 USE 语句,目标库若已存在或权限受限,就会卡在建库阶段。更常见的是,你只想同步表结构(CREATE TABLE),不碰库级操作。
- 加
--no-create-db参数彻底去掉CREATE DATABASE和USE - 加
--skip-triggers --skip-routines --skip-events避免非表结构内容干扰 - 若目标库名和源库名不同,导出后用
sed 's/<code>old_db/new_db/g' 替换库名(注意反引号包裹)
别直接 mysql -u user -p target_db ——没加 <code>--database 时 mysqldump 默认不写库名前缀,导入时容易错绑到当前默认库。
ALTER TABLE 比 CREATE TABLE 更适合线上库结构同步?
是的,尤其当目标表已有数据、不能删重建时。CREATE TABLE 导入会报 ERROR 1050 (42S01): Table 'xxx' already exists,而 ALTER TABLE 可精准追加字段、改类型、调索引。
- 先用
mysqldump --no-data --skip-triggers --skip-routines source_db table_name导出源表 DDL - 用
pt-online-schema-change(Percona Toolkit)生成兼容线上业务的变更语句,避免锁表 - 手动比对
SHOW CREATE TABLE source_db.table_name和SHOW CREATE TABLE target_db.table_name输出,只提取差异部分写成ALTER TABLE
注意:MySQL 8.0+ 的 ADD COLUMN 默认算法是 INSTANT,但加主键、改字段类型仍需 COPY,大表务必在低峰期操作。
从 MySQL 5.7 迁到 8.0,timestamp 默认值报错怎么处理?
MySQL 8.0 严格限制 timestamp 默认值为 CURRENT_TIMESTAMP 且不允许多个字段同时设该默认值,而 5.7 允许。导入时常见错误:ERROR 1067 (42000): Invalid default value for 'updated_at'。
- 导出时加
--compatible=mysql57,让mysqldump生成兼容旧版语法的 DDL - 或临时在目标库执行
SET sql_mode='ALLOW_INVALID_DATES';(仅会话级,不影响全局) - 更稳妥的是在导入前用
sed替换掉有问题的默认值,例如把DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP拆成两个独立字段约束
别忽略 explicit_defaults_for_timestamp 系统变量——8.0 默认为 ON,5.7 默认为 OFF,这个开关会影响 timestamp 字段隐式行为,必须提前对齐。
跨库同步后,外键和索引名冲突怎么办?
MySQL 不允许同名外键存在于同一库中,而 mysqldump 默认导出的外键名(如 fk_user_id)在跨库迁移后可能与目标库原有外键重名,导致 ERROR 1022 (23000): Can't write; duplicate key in table。
- 导出前先查源库外键命名习惯:
SELECT CONSTRAINT_NAME, TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE CONSTRAINT_SCHEMA = 'source_db' AND CONSTRAINT_NAME LIKE 'fk%'; - 在目标库执行前,统一重命名外键:
ALTER TABLE target_table DROP FOREIGN KEY old_fk_name;,再用新名重建 - 索引名同理,
SHOW INDEX FROM target_table查重,用ALTER TABLE ... DROP INDEX+ADD INDEX new_idx_name替换
真正麻烦的是级联外键依赖链——如果 A 表外键引用 B 表,B 表又引用 C 表,导入顺序错了就会失败。必须按依赖拓扑逆序导入:先 C,再 B,最后 A。











