mysql表名大小写敏感由lower_case_table_names系统变量决定:linux默认0(区分)、windows为1(不区分)、macos为2(创建转小写、比较不区分);修改需初始化时设置或清空datadir后重启,线上库不可热改,开发应统一用小写表名并显式加反引号。

MySQL 表名大小写敏感由什么决定
直接看 lower_case_table_names 系统变量,它不是“开关”,而是定义表名在磁盘和内存中如何存储与比较的策略。Linux 默认值是 0(区分大小写),Windows 是 1(不区分),macOS 是 2(创建时转小写,比较时不区分)。你改配置前必须确认当前 OS 和 MySQL 启动方式——Docker 容器里改了 my.cnf 却没挂载生效,或者 systemd 启动时绕过了配置文件,都会白忙。
修改 lower_case_table_names 的实操前提
这个值只能在初始化 MySQL 实例时设置,或在**完全清空数据目录后重启实例**才安全生效。线上库不能热改:设成 1 后再建表 user,旧表 User 仍存在,但 MySQL 会拒绝访问(报错 Table 'db.User' doesn't exist),因为内部元数据已按小写注册,而磁盘上文件名还是大写。
- 必须停服,删掉
datadir下所有文件(包括ibdata1、ib_logfile*、数据库子目录) - 在
my.cnf的[mysqld]段写明lower_case_table_names=1 - 用
mysqld --initialize重建系统表,再启动 - 应用需重新导出/导入数据(
mysqldump输出的 SQL 中表名保持原样,导入时由新规则统一处理)
不改配置时怎么避免踩坑
开发阶段就统一用小写表名,是最省事的方案。很多 ORM(如 Laravel Eloquent、Django ORM)默认生成小写蛇形命名,但如果你手写 SQL 或用旧脚本,容易混用 UserInfo 和 userinfo。MySQL 5.7+ 在 Linux 上执行 SELECT * FROM UserInfo; 可能成功,但换到 Windows 部署就报错——不是语法错,而是 Table 'db.UserInfo' doesn't exist,因为磁盘上实际是 userinfo.frm。
- 所有 DDL 语句显式用反引号包裹表名:
CREATE TABLE `user_profile`,避免关键字冲突也顺便统一大小写习惯 - CI 流程中加检查:用
mysql -Nse "SELECT table_name FROM information_schema.tables WHERE table_schema='your_db'"扫描是否含大写字母 - Navicat / DBeaver 连接时勾选“将对象名称转换为小写”,防止 GUI 自动生成混合大小写
Docker 环境下特别容易漏掉的点
很多人以为在 docker run 命令里加 --env MYSQL_LOWER_CASE_TABLE_NAMES=1 就行,其实 MySQL 官方镜像并不读这个环境变量;它只认 my.cnf。更隐蔽的是:Alpine 版镜像默认用 /etc/my.cnf,而 Debian 版用 /etc/mysql/my.cnf,挂载错路径等于没配。
- 用
docker exec -it mysql cat /etc/my.cnf确认配置文件真实位置 - 挂载时指定完整路径:
-v $(pwd)/my.cnf:/etc/mysql/my.cnf - 检查容器日志有没有警告:
Ignoring query to other database或lower_case_table_names is set冲突提示
大小写问题从来不是“改个参数就完事”,它卡在 OS 文件系统、MySQL 初始化逻辑、备份恢复流程、以及团队命名约定之间。哪怕只部署一套测试环境,也要先验证 SHOW CREATE TABLE 输出的表名和 ls 看到的 .ibd 文件名是否一致。











