mysql不支持原生四只眼审批,必须通过sql网关+审批中间件实现:拦截高危语句、挂起执行、推送审批、回写结果,并确保审计日志完整记录提交与批准双动作。

MySQL 本身不支持原生的“四只眼”(Four-Eyes Principle)双人审批式审计,即无法在一条 UPDATE 或 DROP TABLE 执行前强制弹出二次确认、要求另一账号签名授权。所谓“四只眼”,本质是流程控制,不是数据库引擎能力——必须靠外围机制补足。
为什么不能只靠 GRANT / REVOKE 实现四只眼
权限系统只决定“谁能做”,不干预“做了要不要生效”。即使你把 DROP 权限从应用账号收回,DBA 仍可直连执行;哪怕限制了 root 远程登录,本地终端敲一条命令仍是单点操作。MySQL 的权限模型是静态授权,没有运行时审批钩子。
-
GRANT和REVOKE不提供审批日志或待办队列 - 触发器(
BEFORE UPDATE)无法阻断语句并跳转到外部审批界面 - 审计插件(如
server_audit)只记录“已发生”,不参与“是否允许发生”
真正可行的四只眼落地方式:SQL 网关 + 审批中间件
把数据库访问全部收口到一层可控代理层,由它拦截高危语句、挂起执行、推送审批、回写结果。这是目前生产环境唯一稳定可审计的路径。
- 使用
ProxySQL或MaxScale作为 SQL 网关,在mysql_query_rules中匹配^DROP|^ALTER TABLE.*RENAME|^TRUNCATE|^DELETE FROM [^ ]+ WHERE等正则,将匹配语句重定向到审批队列表 - 建一张
pending_approval表,字段含sql_text、submitter、submitted_at、approver、status('pending'/'approved'/'rejected') - 审批人通过内部 Web 工具或 CLI 命令(如
APPROVE 'uuid-123')更新状态,后台脚本检测到status = 'approved'后才真正执行原始 SQL - 所有操作(提交、审批、执行)都写入独立审计库,且日志不可删改(
chattr +a锁定文件或写入只追加表)
审计日志里如何体现“双人动作”而非单次操作
单纯启用 server_audit 插件只能看到最终执行者,看不出谁提、谁批。必须让审批动作本身也留下可追溯痕迹。
- 审批中间件执行 SQL 前,先插入一条带上下文的审计记录:
INSERT INTO audit_log (event_type, actor, action, target, context) VALUES ('approval_submit', 'dev_user', 'DROP TABLE users', 'app_db', 'reason=cleanup&ticket=JIRA-123') - 审批通过后,再插入一条:
INSERT INTO audit_log (event_type, actor, action, target, context) VALUES ('approval_grant', 'dba_user', 'DROP TABLE users', 'app_db', 'approved_by=sign_key_0x9a8b') - 最后执行真实语句时,网关在
server_audit.log中记录的user字段应为中间件服务账号(如proxy_service@localhost),而非原始提交人——这能明确区分“操作发起者”和“执行载体”
最容易被忽略的三个细节
很多团队搭完审批流程却过不了等保三级,问题就出在这三处:
- 审批中间件与 MySQL 之间未走
require_secure_transport=ON,导致审批指令明文传输 -
pending_approval表没设DEFINER = CURRENT_USER视图隔离,审批人能直接查到他人待审语句(违反最小权限) - 审批超时策略缺失:没人审批时,SQL 一直挂着?还是自动拒绝?必须明确配置
approval_timeout = 3600并写入 SLA 协议











