必须在mysql首次启动前设置lower_case_table_names=1,否则迁移后因文件名与元数据错位导致“table doesn't exist”;linux默认为0,windows为1,配置重启无法修复已错位的表,mysql 8.0初始化后不可更改。

必须在目标 MySQL 实例首次启动前设置 lower_case_table_names=1,否则迁移后必然报 “Table 'xxx' doesn't exist” —— 这不是配置没生效,而是物理文件名和元数据已永久错位。
为什么改了配置重启还是查不到表
Linux 下默认 lower_case_table_names=0,Windows 下默认为 1。迁移时若源库建在 Windows(如 UserOrder.frm),目标库在 Linux 且未提前设 1,MySQL 就会按小写路径去找 userorder.frm,但磁盘上仍是大写文件名,自然找不到。
-
SELECT @@lower_case_table_names;返回1只说明参数加载成功,不代表旧表能访问 -
SHOW TABLES;可能仍列出UserOrder,因为元数据里还存着这个名字,但底层文件不匹配 - 如果中间执行过
DROP DATABASE,MySQL 会用小写路径去删文件,导致大写.frm残留,出现“可见却不可查”的假象
MySQL 8.0 必须初始化时设置,改配置直接拒绝启动
MySQL 8.0 引入了数据字典强校验机制:lower_case_table_names 值必须与初始化时一致,否则服务根本起不来,错误日志里会出现类似:
[ERROR] [MY-011087] Different lower_case_table_names settings for server ('1') and data dictionary ('0')
- 该错误不是警告,是致命拒绝——连进程都不会拉起来
- 不能靠“改配置 + 重启”修复,必须清空
datadir并重新初始化 - 确认
datadir空:检查/var/lib/mysql/下无数据库子目录、ibdata1、ib_logfile*等残留文件
已经导入数据,只能手动逐个重命名
没有自动转换工具,所有大小写不一致的表都得人工 RENAME,且每一步都有陷阱:
- 先执行
SHOW TABLES;,再对比ls /var/lib/mysql/your_db/,找出磁盘文件名(如UserOrder.frm)与元数据(如UserOrder)不一致的表 - 执行
RENAME TABLE `UserOrder` TO `userorder`;—— 反引号必须包裹原名,否则 MySQL 把大写字母当语法错误 - 如有外键或视图依赖该表,需先
SET FOREIGN_KEY_CHECKS = 0;,重命名完再设回1 - 存储过程、触发器、事件里的硬编码表名不会随
RENAME自动更新,必须人工 grep 源码并修改
Docker 和 systemd 容易忽略的加载路径问题
改了容器内的 my.cnf 却没生效?很可能是配置根本没被加载:
- 运行中确认实际加载路径:
mysqld --verbose --help | grep "Default options" - Docker 场景下,确保
my.cnf正确挂载到容器内/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf,且权限为644、属主为mysql - systemd 启动时可能绕过标准路径,检查
systemctl cat mysqld看是否指定了自定义--defaults-file
最常被忽略的是:开发侧用 UserOrder 写 SQL,上线后靠 lower_case_table_names=1 硬扛,结果一换云数据库(RDS 默认锁定为 1 且不可改)就崩。真正可持续的做法,是统一用小写建表、查询、代码引用——参数只是兜底,不是替代方案。











