如何通过Grant语法精确限制MySQL普通用户的删除权限?
- 内容介绍
- 文章标签
- 相关推荐
本文共计885个文字,预计阅读时间需要4分钟。
普通用户不应该拥有《DELETE` 权限,这是数据库安全的基石。直接使用《GRANT ALL PRIVILEGES ON *.*》授予新用户权限,等同于将删除数据库的钥匙递给对方——那他可能只是一个只会读取报表的用户。
明确禁止 DELETE 时,别用 ALL PRIVILEGES
很多人图省事写 GRANT ALL PRIVILEGES ON testdb.* TO 'reporter'@'%',结果发现这个用户能删表、删行、删整个库。ALL 是真·全权委托,包含 DELETE、DROP、ALTER 等高危权限。
正确做法是显式列出需要的权限:
-
SELECT必须保留(否则查不了数据) -
INSERT和UPDATE按业务需要决定是否开放 - 绝对不写
DELETE,也不写ALL - 如果只需要查,就只给
SELECT;如果还要导出或临时写中间表,再加CREATE TEMPORARY TABLES(注意这不是CREATE)
grant 语句里漏掉 flush privileges 不会立即生效
MySQL 的权限不是实时加载的,它把权限缓存在内存里。你执行完 GRANT SELECT, INSERT ON testdb.* TO 'reporter'@'%' 后,该用户可能仍连不上、或权限没变——因为缓存没刷新。
必须手动执行:
FLUSH PRIVILEGES;
常见误区:
- 以为重启 MySQL 才生效(没必要,且影响服务)
- 在非 root 用户下执行
FLUSH PRIVILEGES报错(需RELOAD权限,一般只有管理员有) - 忘记这步,反复测试权限失败,最后怀疑语法写错
回收已有用户的 DELETE 权限要用 REVOKE,不是 GRANT
如果用户已经拥有 DELETE 权限,不能靠“重新 GRANT 一遍不含 DELETE 的权限”来覆盖——MySQL 不会自动撤销旧权限,只会叠加新增的。
必须用 REVOKE 显式收回:
REVOKE DELETE ON testdb.* FROM 'reporter'@'%';<br>FLUSH PRIVILEGES;
注意点:
-
REVOKE只能撤回之前GRANT过的权限,不能撤回未授过的权限(不会报错,但无效) - 如果当初是用
GRANT ALL给的,REVOKE DELETE有效;但如果想彻底清空,得REVOKE ALL PRIVILEGES+GRANT新权限组合 - 撤回后务必
FLUSH PRIVILEGES,否则用户仍可继续删数据
host 部分写 '%' 和 'localhost' 是两个完全不同的账户
MySQL 认证时用的是 'username'@'host' 全匹配。这意味着:
-
'reporter'@'%'和'reporter'@'localhost'是两个独立账户,权限互不影响 - 你在远程机器上连的是
'reporter'@'%',但在本机用mysql -u reporter默认走localhost,可能权限完全不同 - 检查权限时,一定要用
SHOW GRANTS FOR 'reporter'@'%',而不是SHOW GRANTS(后者只显示当前登录用户的权限)
最容易被忽略的是:开发测试时本地连 localhost 没问题,上线后应用连 % 却报错——其实根本就是两套权限配置,压根没给过远程账户 SELECT。
本文共计885个文字,预计阅读时间需要4分钟。
普通用户不应该拥有《DELETE` 权限,这是数据库安全的基石。直接使用《GRANT ALL PRIVILEGES ON *.*》授予新用户权限,等同于将删除数据库的钥匙递给对方——那他可能只是一个只会读取报表的用户。
明确禁止 DELETE 时,别用 ALL PRIVILEGES
很多人图省事写 GRANT ALL PRIVILEGES ON testdb.* TO 'reporter'@'%',结果发现这个用户能删表、删行、删整个库。ALL 是真·全权委托,包含 DELETE、DROP、ALTER 等高危权限。
正确做法是显式列出需要的权限:
-
SELECT必须保留(否则查不了数据) -
INSERT和UPDATE按业务需要决定是否开放 - 绝对不写
DELETE,也不写ALL - 如果只需要查,就只给
SELECT;如果还要导出或临时写中间表,再加CREATE TEMPORARY TABLES(注意这不是CREATE)
grant 语句里漏掉 flush privileges 不会立即生效
MySQL 的权限不是实时加载的,它把权限缓存在内存里。你执行完 GRANT SELECT, INSERT ON testdb.* TO 'reporter'@'%' 后,该用户可能仍连不上、或权限没变——因为缓存没刷新。
必须手动执行:
FLUSH PRIVILEGES;
常见误区:
- 以为重启 MySQL 才生效(没必要,且影响服务)
- 在非 root 用户下执行
FLUSH PRIVILEGES报错(需RELOAD权限,一般只有管理员有) - 忘记这步,反复测试权限失败,最后怀疑语法写错
回收已有用户的 DELETE 权限要用 REVOKE,不是 GRANT
如果用户已经拥有 DELETE 权限,不能靠“重新 GRANT 一遍不含 DELETE 的权限”来覆盖——MySQL 不会自动撤销旧权限,只会叠加新增的。
必须用 REVOKE 显式收回:
REVOKE DELETE ON testdb.* FROM 'reporter'@'%';<br>FLUSH PRIVILEGES;
注意点:
-
REVOKE只能撤回之前GRANT过的权限,不能撤回未授过的权限(不会报错,但无效) - 如果当初是用
GRANT ALL给的,REVOKE DELETE有效;但如果想彻底清空,得REVOKE ALL PRIVILEGES+GRANT新权限组合 - 撤回后务必
FLUSH PRIVILEGES,否则用户仍可继续删数据
host 部分写 '%' 和 'localhost' 是两个完全不同的账户
MySQL 认证时用的是 'username'@'host' 全匹配。这意味着:
-
'reporter'@'%'和'reporter'@'localhost'是两个独立账户,权限互不影响 - 你在远程机器上连的是
'reporter'@'%',但在本机用mysql -u reporter默认走localhost,可能权限完全不同 - 检查权限时,一定要用
SHOW GRANTS FOR 'reporter'@'%',而不是SHOW GRANTS(后者只显示当前登录用户的权限)
最容易被忽略的是:开发测试时本地连 localhost 没问题,上线后应用连 % 却报错——其实根本就是两套权限配置,压根没给过远程账户 SELECT。

