不同用户访问同一数据库是否安全?
不安全,除非你已显式配置权限隔离。MySQL 默认不按用户自动隔离数据——
SELECT、
UPDATE、
DELETE等操作能否执行,完全取决于该用户被授予的
GRANT权限,而非数据库或表名本身。同一个库下,用户 A 可能对
users表有读写权,而用户 B 只能查
logs表,这必须靠人工配,不是 MySQL 自动保障的。
如何用 GRANT 实现最小权限隔离?
核心是「按需授权」:只给每个用户访问其业务必需的库、表、甚至字段的权限。常见错误是直接
GRANT ALL ON mydb.* TO 'user'@'%',这等于交出整把钥匙。 按表授权:
GRANT SELECT, INSERT ON mydb.orders TO 'app_writer'@'10.0.1.%';按列授权(仅 SELECT):
GRANT SELECT(id, status) ON mydb.orders TO 'report_reader'@'10.0.2.%';禁止跨库访问:不显式
GRANT其他库,用户就无法
USE other_db或
SELECT FROM other_db.table及时回收:
REVOKE DELETE ON mydb.users FROM 'app_writer'@'10.0.1.%';比删用户更稳妥
容易被忽略的权限陷阱
权限生效不是即时的,且某些操作绕过常规限制:
SHOW DATABASES权限默认关闭:未授权用户看不到其他库名,但若已知库名仍可
USE xxx尝试访问(只要权限允许) 超级用户(
SUPER、
PROCESS、
REPLICATION CLIENT)权限会破坏隔离,比如
PROCESS可看到所有连接的 SQL,含敏感查询 视图和存储过程的执行权限独立于底层表:即使用户没查
users表权限,若被授了视图
GRANT SELECT ON mydb.v_user_summary,且视图定义里包含脱敏逻辑,就可能绕过限制——但这也意味着你要审计视图定义本身 MySQL 8.0+ 的角色(
CREATE ROLE)可简化管理,但角色本身不自动继承;必须
GRANT role_name TO user才生效,且
SET DEFAULT ROLE才让会话默认启用
验证权限是否真正生效
别只信
SHOW GRANTS FOR 'u'@'h',要实际测行为。登录目标用户后执行:
SELECT USER(), CURRENT_USER(); USE mydb; SELECT COUNT(*) FROM sensitive_table; -- 应报 ERROR 1142 (42000): SELECT command denied SELECT COUNT(*) FROM allowed_table; -- 应返回数字
注意
CURRENT_USER()返回的是认证用户(即权限匹配来源),
USER()是客户端声明的用户——两者不一致常导致权限误判。如果测试时发现“明明没授权却能查”,先看
CURRENT_USER()是否匹配你
GRANT的那个
'user'@'host'。
权限粒度越细,维护成本越高;但生产环境里,漏掉一个
GRANT DELETE或多开一个
WITH GRANT OPTION,都可能让隔离形同虚设。
