MySQL表名大小写敏感由lower_case_table_names参数决定:0区分大小写,1强制小写存储与匹配,2仅macOS支持(创建保留大小写、比较转小写);该参数不可动态修改,必须停库、清空数据或统一表名后修改配置文件并重启。

MySQL 表名大小写敏感由 lower_case_table_names 决定
它不是“开关式”配置,而是系统级行为控制参数,值不同,语义完全不同。Linux 默认是 0(区分大小写),Windows 是 1(不区分),macOS 是 2(创建时按原样存,比较时转小写)。改这个值前必须停库、清空数据目录或确保表名已统一,否则启动直接失败。
-
lower_case_table_names=0:表名按创建时的大小写存储和比较,SELECT * FROM User和SELECT * FROM user是两个不同表 -
lower_case_table_names=1:所有表名强制转小写存储,查询时也自动转小写匹配,User、USER、user全指向同一张表 -
lower_case_table_names=2:仅 macOS 支持;创建时保留大小写,但比较时转小写 —— 这会导致CREATE TABLE User和CREATE TABLE user能成功,但后续DROP TABLE user可能误删前者
修改 lower_case_table_names 必须在初始化后首次启动前完成
运行中的 MySQL 实例无法动态修改该参数;即使你用 SET GLOBAL lower_case_table_names = 1,也会报错 Variable 'lower_case_table_names' is a read-only variable。唯一生效路径是:停库 → 修改配置文件 → 删除 mysql 系统库以外的所有表(或确保现有表名全部小写)→ 重启。
- 配置位置:在
my.cnf或my.ini的[mysqld]段下添加lower_case_table_names=1 - Linux 下若已有大写表名(如
User),设为1后重启会报错Table 'xxx.User' doesn't exist,因为 MySQL 找不到小写的user.frm或user.ibd - 不要试图用
RENAME TABLE User TO user来“补救”——在lower_case_table_names=0下执行 rename 是安全的,但在=1下 rename 失败率极高,且可能损坏 InnoDB 字典
应用层更稳妥的做法是统一用小写表名 + 显式配置
与其冒险改全局参数,不如从开发规范入手。绝大多数 ORM(如 Laravel Eloquent、Django ORM、MyBatis)默认生成小写表名,只要团队约定建表全用小写,就能避开 90% 的跨平台问题。
- 建表语句始终用小写:
CREATE TABLE users (id INT),而非CREATE TABLE Users - 连接字符串中避免硬编码大小写混用的表名,比如 PHP PDO 查询写成
"SELECT * FROM {$prefix}users",而不是"SELECT * FROM {$prefix}Users" - Docker 部署时,在
my.cnf中固定写死lower_case_table_names=1,并确保初始化 SQL 全小写,比依赖宿主机默认值更可靠
常见错误现象和对应排查点
看到 Table 'db.MyTable' doesn't exist 却确认表存在?先别急着改配置,按顺序检查这几处:
- 登录 MySQL 后执行
SELECT @@lower_case_table_names;,确认当前值,别信文档默认值 - 用
SHOW TABLES;查看实际列出的表名大小写,注意终端是否隐藏了不可见字符(比如末尾空格) - 检查文件系统:进入
datadir对应数据库目录,用ls -la看物理文件名,InnoDB 表是表名.ibd,MyISAM 是表名.MYD,名字必须和SHOW TABLES输出严格一致(当=0时) - 客户端工具(如 DBeaver、Navicat)有时会缓存元数据,换命令行
mysql -u root -p -e "USE db; SHOW TABLES;"验证最准
MySQL 的表名大小写逻辑藏在服务启动那一刻,之后就固化了。很多人卡在“为什么我改了配置没用”,其实根本原因是没意识到它只在初始化阶段起作用 —— 后续所有操作都是对那个初始状态的延续。










