应查performance_schema.threads表识别非常用ip登录,其user和host字段实时反映前台连接来源,异常常藏于host值中,需结合processlist验证、过滤空host,并辅以events_statements_history_long和error_log交叉分析。

查 performance_schema.threads 识别非常用 IP 登录
这个表实时反映所有前台连接,USER 和 HOST 字段直接暴露登录来源。异常行为往往藏在 HOST 值里:比如 '10.200.30.45' 是办公网段,但突然出现 '192.168.123.10' 或 '%',就得立刻盯住。
常见错误现象:只查 USER 忽略 HOST,结果把合法用户从跳板机登录当成异常;或者用 LIKE '%192%' 模糊匹配,漏掉 IPv6 地址或域名形式的 HOST(如 'app-server-03.internal')。
- 执行
SELECT USER, HOST, PROCESSLIST_ID FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND (HOST NOT IN ('10.0.0.%', '172.16.0.%') OR HOST = '%'),按实际信任网段调整NOT IN条件 - 配合
information_schema.PROCESSLIST对比验证:有些连接可能已断开但线程未及时清理,threads表更全,PROCESSLIST更“活” - 注意
HOST为空字符串('')表示本地 socket 连接,不是远程 IP,别误判
用 events_statements_history_long 抓权限变更语句
MySQL 社区版不记录 GRANT、CREATE USER 等操作到 error log,但 performance_schema.events_statements_history_long 能捕获它们——前提是已启用对应仪器和消费者。
容易踩的坑:直接查 SQL_TEXT LIKE 'GRANT%' 会漏掉带换行或空格的语句;TIMER_START 是纳秒时间戳,用 NOW() 直接比较会永远不匹配。
- 先确认启用:
UPDATE performance_schema.setup_instruments SET ENABLED = 'YES' WHERE NAME = 'statement/abstract/account_management'; - 再开消费者:
UPDATE performance_schema.setup_consumers SET ENABLED = 'YES' WHERE NAME IN ('events_statements_history_long', 'events_statements_current'); - 查最近一小时的高危授权:
SELECT USER, HOST, SQL_TEXT FROM performance_schema.events_statements_history_long WHERE SQL_TEXT REGEXP '^(GRANT|CREATE USER)' AND TIMER_START > (UNIX_TIMESTAMP(NOW() - INTERVAL 1 HOUR) * 1000000000) - 重点看
HOST是否为非运维 IP,以及SQL_TEXT是否含SUPER、REPLICATION CLIENT、FILE等权限
统计失败登录频次需结合 error_log 和脚本
performance_schema 不记录认证失败事件——它只管“连上了之后干了啥”,失败登录全靠 MySQL 错误日志里的 Access denied 行。但日志本身没结构化,得靠外部脚本解析。
性能影响常被低估:每分钟扫一次几 MB 的 error log,用 grep + awk 没问题;但若日志滚动快、文件大,正则匹配慢,脚本可能卡住或漏统计。
- 确保
log_error已配置且可读,用SHOW VARIABLES LIKE 'log_error';确认路径 - 脚本示例(Shell):
grep "$(date -d '1 minute ago' '+%Y-%m-%d %H:%M')" /var/log/mysql/error.log | grep 'Access denied' | awk '{print $11}' | sed 's/[@(]//g' | sort | uniq -c | sort -nr—— 提取失败 IP 并计数 - 阈值建议:5 分钟内同一 IP 出现 ≥3 次失败即告警,避免单次输错密码触发误报
- 别依赖
general_log替代:它记录成功连接,失败连接不写入,完全覆盖不了场景
为什么不能只靠 setup_actors 或 users 表?
performance_schema.setup_actors 是白名单控制表,只影响后续新连接是否被监控,不反映历史行为;mysql.user 表存的是账户定义,不是登录事实——删掉的账户照样能出现在历史连接里。
最典型的误判:看到 mysql.user 里有个 Host = '%' 的账号,就认定是风险点,却没查 threads 表确认它最近是否真被用过;或者把 setup_actors 里没配的用户当成“未授权用户”,其实只是没开启监控而已。
- 真正要对比的是:
mysql.user中的Host列 +threads中的HOST值 +error_log中的实际 IP,三者交叉验证 -
setup_actors只在需要对特定用户做细粒度监控时才动,日常审计不用碰它 - 注意
threads表中USER为空字符串('')的情况:这是系统内部线程(如复制 IO 线程),不是用户登录,别计入统计
真实环境里,异常行为往往跨多个数据源才拼出全貌——threads 表告诉你“谁来了”,events_statements_history_long 告诉你“他干了什么”,error_log 告诉你“谁被拦在外面”。漏掉任意一环,都可能让一次横向移动或提权尝试悄无声息地过去。











