应使用server_audit插件而非general_log:后者无过滤能力,仅支持全量记录;server_audit可通过server_audit_events='connect,query'捕获高危语句,并配合grep正则提取DROP/ALTER/GRANT等关键词,同时需配置JSON输出、日志轮转及权限最小化补救措施。

只记录DROP/ALTER/GRANT等高危语句,别用general_log
general_log 会把所有语句(包括心跳、空查询、SELECT)全记下来,磁盘几小时就爆满,主库响应变慢,根本没法“只记录高危SQL”。它不区分权限、不支持事件过滤,纯粹是调试开关,不是审计工具。
真正能按语句类型筛选的,只有 server_audit(MariaDB 兼容版)或企业版 audit_log 插件。社区版 MySQL 必须用前者。
-
server_audit_events必须显式包含query,否则连 SQL 文本都不会输出 - 仅靠
server_audit_excl_users排除监控账号没用——高危操作往往来自有权限的 DBA 账号,得靠语句内容过滤 - 日志里看到的
"record":"query"不代表有 SQL,要确认插件是否启用了query事件类型
用server_audit_events + 正则规则过滤高危SQL
server_audit 本身不支持 SQL 内容正则匹配,但可通过组合配置缩小范围:先启用 query 事件,再用外部工具(如 grep 或 SIEM)对日志做关键词提取。
关键配置项必须设对:
-
server_audit_events = 'connect,query'——connect不能漏,否则无法关联执行者身份 -
server_audit_output_type = 'file'—— JSON 格式更易解析,但需确保server_audit_file_path目录可写且属主为mysql -
server_audit_file_rotate_size = 1073741824(1GB)+server_audit_file_rotations = 5—— 防止单个日志滚大后难处理
日志生成后,用以下命令快速抓出高危操作:
grep -E '(DROP|ALTER|TRUNCATE|GRANT|REVOKE|INSTALL PLUGIN|SET GLOBAL)' /var/log/mysql/server_audit.log
注意:CREATE USER、DROP USER、FLUSH PRIVILEGES 也应加入关键词列表,它们常被用于提权链。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
为什么audit_log插件在社区版里看不到SQL内容
MySQL 社区版自带的 audit_log 插件(即使能加载成功)默认不记录 SQL 文本,只记事件类型(如 "command": "Query"),"query" 字段为空。这是设计限制,不是配置错误。
验证方法:查 information_schema.PLUGINS 确认状态为 ACTIVE 后,执行一条 DROP TABLE t1,再看日志文件——你只会看到结构化事件,没有具体语句。
- 企业版才能通过
audit_log_include_tables或策略扩展实现 SQL 内容捕获 - 社区版若强行依赖
audit_log,等于审计盲区;必须换server_audit.so并严格匹配 MySQL 主版本和架构(x86_64/aarch64) -
SHOW VARIABLES LIKE 'plugin_dir'返回的路径才是唯一有效插件加载位置,复制错目录会导致INSTALL PLUGIN报Can't open shared library
绕过权限检查的高危操作仍可能漏记
有些操作看似“没执行 SQL”,实则危害极大,比如通过 GRANT PROXY 登录后执行语句、用存储过程封装 DROP、或通过 LOAD DATA LOCAL INFILE 读取服务器文件——这些在 server_audit 日志里可能只显示为 query 事件,无具体语句,甚至被折叠。
补救手段有限,但必须做:
- 定期运行:
SELECT user, host FROM mysql.user WHERE Super_priv = 'Y' OR Repl_slave_priv = 'Y';,对结果逐个执行SHOW GRANTS FOR 'user'@'host'; - 禁用
local_infile:启动参数加local_infile=OFF,并确认SELECT @@local_infile;返回OFF - 检查代理权限:
SELECT * FROM mysql.proxies_priv;,删除不必要的GRANT PROXY记录
真正的难点不在怎么记,而在“记什么才算数”——SQL 文本可能被截断(受 max_allowed_packet 限制)、存储过程内语句不展开、PREPARE/EXECUTE 动态 SQL 只记模板。这些不是配置能解决的,得靠权限最小化 + 行为基线比对。

















