如何通过数据库代理过滤高危SQL指令_配置拦截Delete与Drop语句

2026-05-21数据库224705

ProxySQL 是目前最可行的、能在 MySQL 层面动态拦截 DROP 和 DELETE 语句的方案——它不依赖权限系统,也不需要改应用代码,靠规则匹配 + 语义前置判断就能在 SQL 执行前拦住;MySQL 原生权限模型无法细化 DROP 到表级,DELETE 授权后仍无法限制无 WHERE 全表删,且权限只管“能不能”,不管“该不该”,而 ProxySQL 可结合用户、schema、SQL 模式、客户端 IP 等做组合策略拦截。

ProxySQL 是目前最可行的、能在 MySQL 层面动态拦截 DROPDELETE 语句的方案——它不依赖权限系统,也不需要改应用代码,靠规则匹配 + 语义前置判断就能在 SQL 执行前拦住。

为什么不能只靠 MySQL 权限控制 DROP/DELETE

MySQL 原生权限模型里:DROP 是库级权限,无法细化到某张表;DELETE 虽然可按表授权,但一旦开了,就拦不住无 WHERE 条件的全表删。更关键的是:权限控制不了「谁在什么时间、用什么客户端、连哪个 IP」执行了高危语句——它只管“能不能”,不管“该不该”。而 ProxySQL 可以结合用户、schema、SQL 模式、甚至客户端 IP 做组合策略。

mysql-acl 规则如何精准匹配 DROP 和危险 DELETE

ProxySQL 的 mysql-acl 不是简单关键词匹配,它支持正则 + 语义上下文,避免误杀正常业务 SQL(比如 DELETE FROM logs WHERE created_at 是合理操作)。

  • 匹配 DROP TABLE 必须区分大小写和空格边界:^DROP[[:space:]]+TABLE[[:space:]]+[a-zA-Z0-9_]+,否则会误中 ALTER TABLE ... DROP COLUMN
  • 拦截无 WHEREDELETE:用 ^DELETE[[:space:]]+FROM[[:space:]]+[a-zA-Z0-9_]+[[:space:]]*;$,注意结尾分号和空格组合,避开带子查询或 JOIN 的合法 DELETE
  • 禁止跨 schema 操作:加条件 match_digest = 'DROP' AND username = 'app_user' AND schemaname = 'production',让规则只对生产账号生效
  • 所有规则必须设 active = 1apply = 1,否则只是摆设

配置后必须验证的三个关键点

光写规则不验证,等于没配。ProxySQL 规则生效有隐藏依赖:

  • 确认 mysql_servers 中后端 MySQL 实例的 hostgroup_idmysql_query_rules 中的 destination_hostgroup 对得上,否则规则根本不会触发
  • 执行 SELECT * FROM mysql_query_rules WHERE active=1 后,一定要运行 LOAD MYSQL QUERY RULES TO RUNTIME,再 SAVE MYSQL QUERY RULES TO DISK,缺一步就白忙
  • 测试时用真实连接(如 mysql -h 127.0.0.1 -P 6033 -u app_user -p),别用 mysql -S /tmp/proxysql.sock —— Unix socket 连接绕过 query rules

真正难的不是写几条正则,而是把规则嵌进你的运维闭环里:每次上线新服务、新增账号、切换主从,都要同步检查 mysql_query_rules 是否仍覆盖当前流量路径。漏掉一次,就可能让一条 DROP TABLE orders 直达主库。

标签: