MySQL 命令历史默认不保存,~/.mysql_history
需手动启用且不可靠
MySQL 客户端(
mysql命令行工具)默认会把执行过的 SQL 写入用户家目录下的
~/.mysql_history文件,但这个行为受多个条件限制:
• 只有在未设置环境变量
MYSQL_HISTFILE为
/dev/null或空字符串时才生效
• 若用户以
mysql -e "SELECT 1"方式执行命令,语句不会写入历史文件
•
~/.mysql_history是纯文本、无时间戳、无用户标识、无连接上下文,无法区分是哪个账号、连的哪台实例、何时执行的
• 文件权限若配置不当(如被其他用户可读),反而构成安全风险
真正的权限审计必须依赖 MySQL 服务端日志,不是客户端历史
要审计“谁在什么时候对哪些表执行了什么操作”,必须开启并解析服务端日志,而非依赖客户端文件。关键选项如下:
•
general_log = ON:记录所有语句(含 SELECT),但 I/O 开销大,仅建议临时开启
•
audit_log = ON(需安装
audit_log.so插件):专为审计设计,支持按用户、命令类型、库/表过滤,输出为 JSON 或 XML
•
binlog不适合直接审计:它记录的是数据变更的逻辑事件(如
Write_rows_event),不含原始 SQL、不记录 SELECT、且需解析二进制格式
INSTALL PLUGIN audit_log SONAME 'audit_log.so'; SET GLOBAL audit_log_policy = 'ALL'; SET GLOBAL audit_log_format = 'JSON';
用 performance_schema
实时抓取活跃会话与最近语句(无需重启)
如果无法开启通用日志或审计插件(例如云数据库 RDS 通常禁用这些功能),可用
performance_schema作为轻量替代方案,但它只保留内存中的近期数据:
•
performance_schema.threads显示当前连接线程及
PROCESSLIST_USER/
PROCESSLIST_HOST
•
performance_schema.events_statements_current包含每个线程最后执行的完整 SQL(字段
SQL_TEXT)
• 注意:默认只保留最近 100 条/线程,且重启后清空;需提前确认
performance_schema已启用,并调大相关 consumer 表容量
SELECT THREAD_ID, USER, HOST, SQL_TEXT FROM performance_schema.events_statements_current JOIN performance_schema.threads USING (THREAD_ID) WHERE SQL_TEXT IS NOT NULL AND SQL_TEXT NOT LIKE 'SELECT %';
权限变更本身必须查 mysql.user
和 mysql.db
表快照,不能靠日志回溯
MySQL 不自动记录 “张三的 SELECT 权限何时被授予 test.*” 这类元操作。权限修改(
GRANT/
REVOKE)虽会记入通用日志(如果开着),但更可靠的方式是定期导出权限快照:
• 执行
SELECT User, Host, Select_priv, Insert_priv, ... FROM mysql.user;
• 执行
SELECT User, Host, Db, Select_priv, ... FROM mysql.db;
• 将结果保存为带时间戳的 CSV,用 diff 工具比对差异
• 注意:直接查询
mysql系统库需
SELECT权限,且部分字段(如密码哈希)在 8.0+ 中已移至
mysql.user的
authentication_string权限审计真正难的不是“怎么记”,而是“记下来之后谁来读、多久读一次、异常如何告警”。
~/.mysql_history连基础溯源都做不到,别把它当审计依据。
