必须用mysqldump逻辑导出再导入,禁用直接拷贝data/目录;导出需加--single-transaction和--default-character-set=utf8mb4,避免锁表卡顿、字符集错乱及bom导致语法错误;导入前须手动建库并指定utf8mb4字符集,且导入命令也需显式指定--default-character-set=utf8mb4。

不能直接拷贝 data/ 目录,必须用 mysqldump 逻辑导出再导入。物理迁移在跨平台场景下几乎必然失败,不是数据损坏,而是文件系统、大小写策略和权限模型根本不同。
导出时必须加 --single-transaction 和 --default-character-set=utf8mb4
Windows 客户端默认字符集常为 cp1252 或 gbk,而 Linux MySQL 服务端通常设为 utf8mb4。不显式指定,mysqldump 会按 Windows 环境读取内容,导出的 SQL 文件头可能没声明编码,导入时触发二次转码,中文变 ? 或乱码。
-
--single-transaction避免对 InnoDB 表执行FLUSH TABLES WITH READ LOCK,否则在 Windows 上可能卡住业务写入;更关键的是,该锁在 Linux 导入时若超时(尤其大库),mysql客户端会静默中断连接,导致部分表导入失败但无明确报错 - 若库含存储过程、函数或事件,额外加
--routines --events,否则这些对象不会被导出 - 导出后检查 BOM:用
head -c 3 mydb.sql | xxd查看,若有ef bb bf就需去除——记事本保存过极易引入 BOM,Linux 下执行会直接报ERROR 1064
导入前必须手动建库并显式指定 utf8mb4 字符集
mysqldump --databases 生成的 SQL 中虽有 CREATE DATABASE 语句,但 Linux MySQL 默认忽略它(尤其当目标库已存在时),也不会校验字符集是否匹配。结果就是:库能创建、表能建、数据能插,但 SHOW CREATE TABLE 显示 CHARSET=utf8(实为 utf8mb3),emoji 插入失败或被截断。
- 先在 Linux MySQL 中执行:
CREATE DATABASE `mydb` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 导入时也指定字符集,防止客户端连接层二次转码:
mysql --default-character-set=utf8mb4 -u root -p mydb - 别用
source mydb.sql进 MySQL 客户端——大文件易因网络/超时中断,且错误定位困难
lower_case_table_names=1 必须在首次启动前设置
Windows 默认 lower_case_table_names=1(不区分大小写),Linux 默认是 0(区分大小写)。迁移后若未显式设置,表名含大写字母(如 UserInfo)在 Linux 上能创建、能 SELECT,但后续任何 ALTER TABLE UserInfo 或 mysqldump 备份脚本都会失败——报 Table 'userinfo' doesn't exist,因为内部元数据比对时把大小写当成了不同对象。
- 该参数在 MySQL 8.0+ 是只读的:修改后必须删除
datadir下的ibdata1、ib_logfile*和所有数据库子目录(保留mysql.sock所在结构),再用mysqld --initialize-insecure重新初始化 - 验证方法:建一个含大写字母的表
CREATE TABLE TestTable (id INT),再用小写查SHOW TABLES LIKE 'testtable';——应该能返回结果才算生效 - 如果已经导入了数据,无法一键修复:只能逐个
RENAME TABLE `UserOrder` TO `userorder`,注意反引号包裹原名;外键或视图依赖该表名的,得先SET FOREIGN_KEY_CHECKS = 0
最危险的坑不是导不出,而是导出成功、导入成功、查询也成功,但 lower_case_table_names 没提前设,后续 DDL 和备份全部静默失败——这种问题往往上线后才暴露,排查成本极高。











