MySQL表名大小写敏感性由lower_case_table_names决定:0区分大小写(Linux默认),1强制小写存储且比较不区分,2保留大小写但比较转小写(macOS默认);修改该值需停库导出、清数据目录、重初始化并导入,否则启动失败。

MySQL 表名是否区分大小写,完全由 lower_case_table_names 配置决定,但改它不是“设个参数就完事”——设错会直接导致库启动失败或表找不到。
为什么改了 lower_case_table_names 服务起不来?
MySQL 启动时会校验现有数据目录里的表文件名和配置是否兼容。如果原库是 lower_case_table_names=0(区分大小写),你改成 1 或 2 后直接重启,MySQL 会拒绝启动,并报错:Cannot start MySQL server. Table 'xxx' doesn't exist.
- 根本原因是:表文件名(如
MyTable.frm、mytable.ibd)和数据字典里记录的表名不一致 -
lower_case_table_names=1要求所有表名在磁盘上都小写,但老库可能有User、USER、user多个同名不同大小写的表,物理上冲突 - Windows 和 macOS 默认用
1,Linux 默认用0;跨平台迁移时最容易踩这个坑
线上库想统一成小写表名,必须做三件事
不能只改配置文件,否则等于给 MySQL 下达一个“自相矛盾”的指令。
- 先停库,用
mysqldump导出全部数据(注意加--databases和--set-gtid-purged=OFF,避免 GTID 冲突) - 删掉旧的
datadir目录(或重命名备份),初始化新实例(mysqld --initialize),再修改配置文件中的lower_case_table_names=1 - 重启 MySQL,再用
mysql命令导入 dump 文件——此时所有表名会被自动转为小写存入磁盘
lower_case_table_names 的三个取值到底影响什么?
不是“要不要转小写”那么简单,它决定了表名的存储、比较、查找三层行为:
-
0:表名按创建时的大小写保存,比较也区分大小写(Linux 默认)。写SELECT * FROM User;和SELECT * FROM user;可能查不同表 -
1:表名始终转为小写存储,比较时不区分大小写。建CREATE TABLE USER(...),实际生成user.frm和user.ibd -
2:表名按创建时大小写保存,但比较时转小写(macOS 默认)。适合兼容老脚本但又不想强制小写磁盘名的场景
注意:lower_case_table_names 是只读变量,运行中无法 SET;且一旦设为 1,就不能再设回 0,除非彻底重建库。
开发环境误配导致本地跑不通线上 SQL
常见现象:SQL 在测试环境(macOS,lower_case_table_names=2)能执行,一上 Linux 生产(默认 0)就报 Table 'db.User' doesn't exist。
- 根本原因:SQL 里写了大驼峰表名(如
UserProfile),而生产库严格区分大小写,但表实际是userprofile - 解决方案不是调配置,而是统一代码和建表语句:全部用小写下划线(
user_profile),或至少确保 SQL 中的表名和SHOW TABLES输出完全一致 - Docker 环境尤其要注意:镜像默认配置可能和宿主机不一致,必须显式挂载自定义
my.cnf并确认lower_case_table_names值
最麻烦的不是设不对,而是设了之后没验证表名落地形态——用 ls -l /var/lib/mysql/your_db/ 看物理文件名,比查文档更可靠。


















