mysql默认不记录登录失败日志,必须设log_error_verbosity=3并重启服务、确保log_error路径可写,才能在错误日志中捕获“access denied”事件;general_log等其他日志无法记录认证失败。

MySQL 默认不记录连接失败尝试,必须显式启用详细错误日志级别并确认日志路径可写、服务已重启;否则 Access denied 类事件根本不会落盘。
log_error_verbosity = 3 是硬性前提
MySQL 8.0+ 中,只有该参数设为 3 才会把认证失败(如密码错、用户不存在)作为 Note 级别写入错误日志。值为 1 或 2 时,Access denied for user 这类行直接被过滤掉。
- 执行
SET GLOBAL log_error_verbosity = 3仅临时生效,必须写入配置文件才持久 - 配置位置:在
[mysqld]段下添加log_error_verbosity = 3 - 验证是否生效:用错误密码连一次,再执行
tail -n 10 /var/log/mysql/error.log | grep "Access denied",有输出才算成功
log_error 路径必须可写且被 MySQL 进程拥有
即使配置了 log_error = /var/log/mysql/error.log,如果 MySQL 用户(通常是 mysql)对该路径无写权限,日志会静默失效——你查 SHOW VARIABLES LIKE 'log_error' 看到路径是对的,但文件始终为空或只记启动信息。
- 检查权限:
ls -ld /var/log/mysql/,确保属主是mysql:mysql,至少有drwxr-xr-x - 若目录不存在,手动创建并赋权:
sudo mkdir -p /var/log/mysql && sudo chown mysql:mysql /var/log/mysql - 不要用
/tmp或用户家目录——MySQL 启动早于用户会话,可能因权限或 SELinux 拒绝写入
避免被 general_log 或 performance_schema 带偏
有人试图用 general_log = ON 抓失败连接,这是无效的:general_log 只记录“已建立”的连接请求,而权限拒绝发生在握手阶段之前,压根不会进这个日志;performance_schema.threads 里也找不到失败连接的痕迹,因为它们没活过初始化。
- 唯一可靠信号源就是错误日志里的
Access denied for user行,它明确表示校验失败 - 注意时间戳格式差异:MySQL 8.0+ 默认用 ISO 格式(如
2026-06-11T23:45:01.123456Z),用date -d "60 seconds ago" "+%Y-%m-%dT%H:%M"匹配更准,别用老式%b %d %H:%M - 中间件(如 ProxySQL)可能伪造该日志行,需结合
@'host'字段过滤真实客户端 IP,排除类似'proxy'@'127.0.0.1'的条目
真正难的不是配置,而是意识到 MySQL 从不“主动记录失败连接”,它只在权限校验失败后,按当前 log_error_verbosity 级别决定是否把那句 Access denied 当作一条普通日志写出去——漏掉这一层理解,所有排查都会绕远路。











