SQL只读账号需从权限控制、连接约束、审计追踪三方面协同防护:严格授予SELECT权限并禁用其他操作,配置数据库只读参数与SQL拦截规则,规范连接字符串与工具使用,并启用审计日志与实时告警机制。

SQL只读账号的核心目标是:让指定用户只能执行 SELECT,不能改动任何数据或结构。配置本身不难,但要真正防住误操作,得从权限控制、连接约束、审计追踪三方面一起下手。
一、基础权限配置(按数据库类型区分)
不同数据库的语法和粒度有差异,关键不是“加SELECT”,而是“不给其他权限”:
-
MySQL / MariaDB:用
GRANT SELECT ON db_name.* TO 'user'@'host';,切忌用GRANT SELECT ON *.*;执行后必须FLUSH PRIVILEGES; -
PostgreSQL:先
CREATE ROLE readonly WITH LOGIN PASSWORD 'xxx';,再对每张表运行GRANT SELECT ON TABLE tbl_name TO readonly;;如需批量授权,可用psql -c "SELECT 'GRANT SELECT ON ' || tablename || ' TO readonly;' FROM pg_tables WHERE schemaname = 'public';"生成脚本 -
SQL Server:新建登录名 → 创建数据库用户 → 将其加入
db_datareader角色;禁用db_owner、db_ddladmin等高危角色 -
Oracle:创建用户后,仅授予
CREATE SESSION和SELECT_CATALOG_ROLE(如需查数据字典),避免授CONNECT(含资源权限)或SELECT ANY TABLE
二、限制写操作的“兜底策略”
光靠权限不够——比如用户连错库、用错账号、或应用代码里拼了 UPDATE 却没报错。得加一层保险:
- 在数据库代理层(如 ProxySQL、MaxScale)或中间件中,配置 SQL 拦截规则,直接拒绝
INSERT/UPDATE/DELETE/DROP/ALTER等关键词语句 - MySQL 8.0+ 可启用
read_only=ON(对非 super 用户生效),配合super_read_only=ON防止管理员误开写权限 - PostgreSQL 可设
default_transaction_read_only = on,并禁止用户在会话中执行SET TRANSACTION READ WRITE;(通过ALTER ROLE ... SET固化)
三、连接与使用规范(人和工具层面)
很多误操作来自连错环境或工具自动执行:
- 只读账号的连接字符串中,显式加上
?readonly=true(如 JDBC)或options='-c default_transaction_read_only=on'(psql),让客户端也感知只读意图 - 禁止在生产只读账号中使用图形化工具(如 Navicat、DBeaver)的“自动提交”或“执行所有语句”功能;建议用 CLI 或定制只读插件
- 开发/测试环境的只读账号,应与生产账号完全隔离,且连接串中强制包含环境标识(如
db-prod-readonly),避免复制粘贴出错
四、审计与快速响应机制
防不住100%,但要确保问题可追溯、可拦截:
- 开启数据库通用日志(MySQL
general_log)或审计插件(如 MySQL Enterprise Audit、pgAudit),记录所有非 SELECT 语句的来源 IP、账号、时间、SQL 内容 - 配置告警:当检测到只读账号尝试执行写操作时,立即触发企业微信/钉钉通知,并记录到 SIEM 平台
- 定期跑脚本检查账号权限是否被意外变更(例如对比当前 GRANT 结果与基线清单),发现偏差自动冻结账号并告警
只读账号不是配完就完事,它是一套组合动作:权限最小化 + 连接强约束 + 使用有规范 + 行为可审计。少一个环节,就可能在某个深夜因为一条 DELETE FROM users; 被执行而惊醒。










