MySQL 用户能否自行创建或删除索引?
MySQL 的索引操作本身不依赖独立的权限位,
CREATE INDEX和
DROP INDEX权限并不存在。是否能建/删索引,完全取决于用户对表的
ALTER权限: 有
ALTER权限 → 可执行
CREATE INDEX、
DROP INDEX、
ALTER TABLE ... ADD/DROP INDEX无
ALTER权限 → 即使有
SELECT/
INSERT,也无法增删索引
所以“防止滥用索引权限”的本质,是控制
ALTER权限的授予范围。
常见错误现象: - 开发账号被误授
ALTER,上线后误删线上表的复合索引,导致慢查询暴增 - 测试环境用户用
ALTER TABLE t ADD INDEX (a,b)建了大量单列冗余索引,拖慢 DML 性能
如何最小化授予 ALTER 权限?
生产环境应默认拒绝
ALTER,仅在明确需要时临时授权。具体策略: 禁止给普通应用账号授予
ALTER:应用只读/写数据,不参与 DDL DBA 或运维账号单独管理索引变更:所有
ALTER TABLE ... ADD INDEX必须走审批 + SQL 审核流程 用角色(MySQL 8.0+)隔离权限:创建
index_admin角色,仅包含
ALTER,再将该角色授予少数人 旧版本(5.7)可用存储过程封装索引操作:让开发者调用
CALL add_index('t1', 'idx_a', 'a'),而过程内校验白名单表名和字段名,避免任意 DDL
有没有办法限制索引类型或字段组合?
MySQL 原生不支持“只允许建 B-tree 索引”或“禁止在 text 列上建索引”这类细粒度控制。但可通过以下方式间接约束:
SQL 审计插件(如 MySQL Enterprise Audit 或 Percona Audit Log):捕获所有含CREATE INDEX或
ALTER TABLE ... ADD INDEX的语句,自动告警或拦截含
fulltext、
spatial、或长度超 255 的
varchar字段建索引的行为 代理层拦截(如 ProxySQL、MaxScale):配置规则匹配
CREATE INDEX.<em>(([^)]</em>text|blob|json)[^)]*)类正则,直接拒绝 建表前约定索引规范文档:例如“联合索引字段数 ≤ 3,首字段必须是查询高频等值条件”,靠 Code Review 和 DBA 人工把关
为什么不能靠 GRANT INDEX 权限来控制?
因为
INDEX权限在 MySQL 中仅用于 CREATE TABLE 时内联定义索引,例如:
CREATE TABLE t (id INT, name VARCHAR(50), INDEX(name))
它不控制后续的
CREATE INDEX或
ALTER TABLE ... ADD INDEX—— 这些全由
ALTER权限管辖。
所以即使你执行了:
GRANT INDEX ON db.t TO 'u'@'%'
该用户依然无法独立建索引,除非同时拥有
ALTER。
真正容易被忽略的是:很多团队以为给了
INDEX就安全了,结果开发仍可通过
ALTER绕过——根源在于没理清这两个权限的实际作用域。
