授权语句中库名是否区分大小写取决于lower_case_table_names参数:设为0时严格区分,1时强制转小写存储与匹配,2时存储保留原大小写但比较转小写;该参数启动时读取,运行中不可修改,且直接影响grant/revoke及权限校验行为。

授权语句里库名是否区分大小写,取决于 lower_case_table_names
MySQL 的 GRANT 语句中库名(database name)的大小写行为,不是由 SQL 语法决定的,而是直接受 lower_case_table_names 参数控制。这个参数在启动时读取,决定了 MySQL 如何存储和匹配库名——包括授权系统内部注册的权限记录。
- 当
lower_case_table_names = 1(Windows 默认、推荐跨平台统一值):所有库名被强制转为小写存储。执行GRANT ALL ON MyDB.* TO 'u'@'%';后,实际注册的是mydb;后续用SHOW GRANTS FOR 'u'@'%';查看,或用SELECT * FROM mysql.db WHERE Db='mydb';查询权限表,结果都只认小写。 - 当
lower_case_table_names = 0(Linux 默认):库名按原始大小写存储。GRANT ... ON ProdDB.*和GRANT ... ON proddb.*会被视为两个独立授权项,可能同时存在;但若文件系统不支持同名大小写变体(如 ext4),第二次建库会失败,而授权却可能“成功”写入元数据,导致后续权限校验混乱。 -
lower_case_table_names = 2(macOS 默认)在 Linux 上不可用,且不建议使用——它会导致授权语句中库名大小写不一致:创建时保留UserDB,但匹配时转小写,结果GRANT ... ON userdb.*可能意外命中UserDB,而REVOKE却因大小写拼写不一致失效。
为什么 SHOW GRANTS 显示小写,但 SELECT FROM mysql.db 却看到大写?
这种现象通常说明你正在混合使用不同 lower_case_table_names 值的环境,或者数据库曾被迁移过。例如:
- 从 Windows(
lower_case_table_names=1)导出的 dump 文件,在 Linux(默认=0)上导入后,mysql.db.Db字段里存的是小写(因为 dump 中是小写),但 MySQL 实例本身按=0解析,导致权限匹配失败——GRANT ... ON MyDB.*找不到MyDB对应的记录,因为磁盘上没这个库名,而权限表里又是小写的mydb。 - 更隐蔽的情况:某些备份工具(如 mydumper)导出时未加
--skip-extended-insert,导致表名被自动转义成反引号包裹的小写形式,再导入到=0环境时,GRANT语句里的库名和权限表内容大小写对不上。
授权语句执行成功但权限不生效的常见原因
这不是 bug,而是大小写策略与权限缓存/解析顺序共同作用的结果。重点排查以下几点:
-
FLUSH PRIVILEGES;不解决大小写问题——它只重载权限表,不修正大小写不匹配。 - 用户连接时指定的数据库名(如
mysql -D MyDB)必须与mysql.db表中存储的大小写完全一致(=0时)或自动转小写后一致(=1时)。 - 通配符授权如
GRANT ... ON `test%`.*中的模式匹配,不走lower_case_table_names转换,而是直接字符串比较,因此=0下`TEST%`和`test%`是不同模式。 - MySQL 8.0+ 的角色权限(
CREATE ROLE r; GRANT ... ON db.* TO r;)同样受该参数影响,且角色名本身也区分大小写(=0时)。
线上改 lower_case_table_names=1 会丢权限吗?
会,而且无法自动恢复。因为:
- MySQL 启动时,会按新规则重新解析
mysql.db、mysql.tables_priv等系统表中的库名字段;如果原值是ProdDB,而新规则要求小写,它不会自动把ProdDB改成proddb,而是跳过或报错。 - 更危险的是:改完重启后,旧权限记录仍留在磁盘,但 MySQL 内部不再识别它们——表现为用户能连上,但所有
SELECT、INSERT都提示Access denied,即使SHOW GRANTS看起来正常。 - 安全做法只有两种:① 初始化新实例,设好
lower_case_table_names=1,再用mysqldump --all-databases导入;② 停库,手动更新mysql.db.Db字段为小写,同时重命名数据目录下对应库名的文件夹(如/var/lib/mysql/ProdDB → /var/lib/mysql/proddb),再启动。
真正麻烦的从来不是“怎么设”,而是设之前有没有检查过所有授权语句、备份脚本、ORM 配置里硬编码的库名大小写——这些地方一旦混用,改完配置反而让权限逻辑更难追踪。











