mysql如何给用户分配指定库权限_mysql授权范围说明

来源:这里教程网 时间:2026-02-28 20:37:24 作者:

如何用
GRANT
精确授予指定数据库权限

直接给用户分配「只对某个库有操作权」,是 MySQL 权限管理中最常见也最易出错的场景。核心在于:权限不是绑定到“用户”本身,而是绑定到

'username'@'host'
这个完整账户标识上,且必须显式指定数据库范围(如
myapp_db.*
),不能只写库名或留空。

GRANT SELECT, INSERT ON myapp_db.* TO 'appuser'@'192.168.1.%';
—— 正确:明确限定库、通配表、限制来源 IP 段
GRANT ALL ON myapp_db TO 'appuser'@'%';
—— 错误:缺少
.*
,MySQL 会报错
ERROR 1064 (42000)
GRANT SELECT ON *.* TO 'appuser'@'%';
—— 危险:这是全局只读,可能越权访问其他业务库

执行后务必加

FLUSH PRIVILEGES;
,否则权限不会立即生效(尤其在非 root 用户修改后或配置了
skip-grant-tables
时)。

'%' vs 'localhost'
:为什么授权后还是连不上?

MySQL 把

'user'@'localhost'
'user'@'%'
当作两个完全独立的账户。如果你用客户端从本机连接却用了
mysql -h 127.0.0.1 -u appuser
,实际走的是 TCP 连接,匹配的是
'appuser'@'%'
,而非
'appuser'@'localhost'
(后者仅匹配 Unix socket 或
-h localhost
且未启用 skip-name-resolve 时)。

本地开发常用:先授
'appuser'@'localhost'
,再授
'appuser'@'127.0.0.1'
,覆盖两种本地连接方式
生产环境建议用具体 IP 段(如
'appuser'@'10.10.20.%'
)而非
%
,避免暴露给公网
阿里云/腾讯云 ECS 需额外检查安全组是否放行
3306
端口,且 MySQL 配置中
bind-address
不能为
127.0.0.1
(否则拒绝远程)

只读用户怎么建才真正安全?

只给

SELECT
不等于“只读”——如果用户还能
DROP TABLE
CREATE VIEW
,仍可能间接破坏数据结构或绕过权限逻辑。最小化原则下,应显式排除高危操作。

CREATE USER 'reporter'@'%' IDENTIFIED BY 'StrongPass!2025';
GRANT SELECT ON finance_db.* TO 'reporter'@'%';
-- 不要 GRANT SHOW VIEW、LOCK TABLES、EXECUTE,除非明确需要
REVOKE FILE, PROCESS, SUPER, REPLICATION CLIENT ON *.* FROM 'reporter'@'%';
FLUSH PRIVILEGES;

注意:

REVOKE
只能撤销之前
GRANT
过的权限;若用户已有全局权限,必须先
REVOKE ALL PRIVILEGES ON *.*
再逐库授权,否则旧权限残留。

权限查不全?
SHOW GRANTS
的真实含义

SHOW GRANTS FOR 'appuser'@'%';
显示的是该账户被显式授予的权限,**不包含隐式继承或默认权限**(比如所有账户默认都有
USAGE
,即连接权)。它也不会合并多个
GRANT
语句的结果——如果分别授了
SELECT
INSERT
,这里会显示两条独立记录。

想确认某用户对某张表是否有
UPDATE
权:直接用该用户登录,执行
UPDATE test_table SET x=1 WHERE 1=0;
看是否报
ERROR 1142 (42000): UPDATE command denied
SELECT * FROM mysql.db WHERE User='appuser' AND Db='myapp_db';
可查数据库层级权限原始记录(需
SELECT
权限访问系统表)
权限缓存可能延迟:修改
mysql.user
表后,必须
FLUSH PRIVILEGES;
,否则新连接仍按旧缓存判断

权限粒度越细,排查路径越长。别迷信

SHOW GRANTS
输出,真要用时,始终以「该用户实际能否执行」为准。

相关推荐