sql只读账号的核心是不给写权限、只授查询权,并避免误授高危权限;mysql需显式grant select并禁用写权限,postgresql推荐用role统一管理,sql server可借助db_datareader角色并按需细化。

SQL只读账号的核心是:**不给写权限,只授查询权**,同时避免误授高危权限(如SELECT ANY TABLE或DBA角色)。不同数据库实现方式略有差异,下面以主流场景为主说明关键步骤。
MySQL:用GRANT控制表级/库级只读
MySQL不内置“只读角色”,需显式授予SELECT权限,并确保不授予INSERT/UPDATE/DELETE/DROP等权限。
- 创建用户(MySQL 8.0+ 推荐带身份验证插件):
CREATE USER 'rd_user'@'192.168.1.%' IDENTIFIED BY 'StrongPass123!'; - 授予指定数据库的只读权限:
GRANT SELECT ON myapp_db.* TO 'rd_user'@'192.168.1.%'; - 刷新权限生效:
FLUSH PRIVILEGES; - (可选)禁止用户修改自身密码或访问系统库:
REVOKE CREATE USER, SUPER, REPLICATION CLIENT ON *.* FROM 'rd_user'@'%';
并确认未授予mysql库权限。
PostgreSQL:用ROLE + GRANT实现最小化只读
PostgreSQL推荐通过角色(ROLE)统一管理权限,再把只读角色赋予用户,便于后期维护。
- 创建只读角色:
CREATE ROLE read_only_role NOLOGIN; - 授予该角色对所有当前及未来表的SELECT权限(需配合
DEFAULT PRIVILEGES):GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only_role;ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO read_only_role; - 创建用户并赋予只读角色:
CREATE USER rd_user WITH PASSWORD 'StrongPass123!';GRANT read_only_role TO rd_user; - (重要)撤回默认的
public角色权限(防止意外访问):REVOKE SELECT ON TABLE pg_catalog.pg_class FROM public;(按需调整)
SQL Server:用db_datareader角色 + 显式限制
db_datareader是SQL Server内置只读角色,但需注意它默认允许查所有用户表——若需更细粒度(如仅某几张表),应拒绝继承后手动授权。
- 创建登录名(SQL认证):
CREATE LOGIN rd_user WITH PASSWORD = 'StrongPass123!'; - 在目标数据库中创建用户并加入只读角色:
USE myapp_db;<br>CREATE USER rd_user FOR LOGIN rd_user;<br>ALTER ROLE db_datareader ADD MEMBER rd_user;
- 如需限制到特定表,先移出角色,再单独授权:
ALTER ROLE db_datareader DROP MEMBER rd_user;<br>GRANT SELECT ON dbo.orders TO rd_user;<br>GRANT SELECT ON dbo.customers TO rd_user;
- 确保未授予
db_owner、db_ddladmin等高权限角色。
通用安全建议(跨数据库适用)
只读账号不是“绝对安全”的代名词,配置后还需检查实际行为是否符合预期。
-
禁止连接到系统库/元数据敏感库:如MySQL的
information_schema(除非业务真需要)、PostgreSQL的pg_catalog、SQL Server的master等。可通过网络层或账号作用域限制。 -
限制IP或主机范围:在创建账号时指定
'user'@'10.20.30.%'而非'user'@'%',降低暴露面。 -
定期审计权限:用
SHOW GRANTS FOR ...(MySQL)、\du+(psql)、sp_helprolemember(SQL Server)核对实际权限。 -
避免使用通配符授权:如
GRANT SELECT ON *.*或GRANT SELECT ON DATABASE.*(当DATABASE含多个业务库时风险大)。










