MySQL迁移后表名变小写的根本原因是lower_case_table_names配置不一致:Linux默认为0(区分大小写),Windows/macOS默认为1(强制小写);迁移前须在目标实例启动前配置lower_case_table_names=1并重启,运行中不可修改。

MySQL 迁移后表名变成小写,根本原因是 lower_case_table_names 配置不一致
Linux 系统下 MySQL 默认 lower_case_table_names=0(区分大小写),而 Windows/macOS 默认是 1(强制转小写)。迁移时若源库在 Windows、目标库在 Linux,但没提前统一该参数,就会出现原表 UserOrder 在目标库变成 userorder,导致应用查不到表或报 Table 'db.UserOrder' doesn't exist 错误。
迁移前必须在目标 MySQL 实例中设置 lower_case_table_names=1 并重启
这个参数是只读的,**只能在 mysqld 启动前配置,运行中无法修改**。直接改配置文件再重启是最稳妥的做法:
- 编辑
/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf,在[mysqld]段落下添加:lower_case_table_names=1
- 确保目标实例**首次启动前就已配置**——如果实例已有数据,再设为 1 会导致元数据不一致,可能引发崩溃
- Linux 下必须用
systemctl restart mysql(或mysqld)彻底重启,仅 reload 不生效 - 验证是否生效:连接 MySQL 后执行
SELECT @@lower_case_table_names;,返回1才算成功
mysqldump 导出时加 --skip-set-charset 和显式指定 --default-character-set
虽然和表名大小写无直接关系,但实际迁移中常因字符集混乱加剧表名识别问题。特别是旧库用 latin1、新库默认 utf8mb4 时,mysqldump 可能自动插入错误的 SET NAMES,导致建表语句里表名被错误转义或截断。
- 导出命令推荐:
mysqldump --single-transaction --skip-set-charset --default-character-set=utf8mb4 -u root -p db_name > dump.sql
-
--skip-set-charset防止 dump 文件开头写入SET NAMES latin1类指令 -
--default-character-set=utf8mb4显式声明连接字符集,避免客户端环境干扰 - 导入前检查 dump.sql 中建表语句的表名是否保持原始大小写(如
CREATE TABLE `UserOrder`),若已全小写,说明源库当时lower_case_table_names=1,目标库也必须设为 1
跨平台迁移最保险的实践:统一用小写表名 + 开发侧适配
靠参数硬扛容易翻车,尤其当目标环境无法修改 lower_case_table_names(如云数据库 RDS 通常锁定为 1)时,更应从前端收敛。
- 所有建表语句、SQL 查询里的表名全部用小写,例如
CREATE TABLE user_order而非UserOrder - ORM 框架(如 Laravel Eloquent、Django ORM)配置表名映射时,显式指定小写字符串:
protected $table = 'user_profile'; - 检查现有代码中硬编码的表名、存储过程、视图定义,替换为小写并测试关联逻辑
- 临时应急方案:用
RENAME TABLE批量修复,但仅限于目标库已设lower_case_table_names=1且表尚未被应用访问时 ——RENAME TABLE UserOrder TO userorder;
真正麻烦的不是改配置,而是当目标库已运行多日、参数被锁死、又没法停机,这时就得一层层核对 SQL 日志里实际执行的表名和 INFORMATION_SCHEMA.TABLES 里的记录是否对得上。大小写问题往往只是表象,背后卡住的是整个元数据链路的一致性假设。


















