mysql账号自动锁定需同时设置failed_login_attempts和password_lock_time参数,仅对caching_sha2_password或mysql_native_password用户生效,password_lock_time单位为天(非分钟),0表示永久锁定,锁定期满须成功登录才重置计数并解锁。

MySQL账号自动锁定是靠FAILED_LOGIN_ATTEMPTS和PASSWORD_LOCK_TIME控制的
MySQL 8.0+ 支持基于密码验证失败次数的账户锁定机制,但必须使用caching_sha2_password或sha256_password插件(mysql_native_password不支持)。锁定行为由两个全局/用户级参数决定:FAILED_LOGIN_ATTEMPTS定义连续失败多少次后锁账户,PASSWORD_LOCK_TIME定义锁定持续分钟数(支持小数,如0.1表示6秒)。
注意:这两个参数只对新创建或ALTER修改过的用户生效,已有用户需显式重置密码或执行ALTER USER才能激活锁定策略。
设置用户级自动锁定策略要显式指定FAILED_LOGIN_ATTEMPTS和PASSWORD_LOCK_TIME
不能只改全局变量,必须在创建或修改用户时绑定策略。例如:
CREATE USER 'app_user'@'%' IDENTIFIED BY 'Passw0rd!' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 1;
或者对已有用户启用:
ALTER USER 'app_user'@'%' FAILED_LOGIN_ATTEMPTS 3 PASSWORD_LOCK_TIME 0.5;
-
PASSWORD_LOCK_TIME设为0表示永久锁定,需DBA手动ALTER USER ... ACCOUNT UNLOCK - 设为
DEFAULT会继承全局值(如果全局未设,则为0) - 若只设
FAILED_LOGIN_ATTEMPTS而没设PASSWORD_LOCK_TIME,锁定时间默认为0(即不锁) - 修改后立即生效,无需重启
检查账号是否被锁定要看account_locked字段和错误信息ERROR 3956
锁定状态不体现在mysql.user表里,得查performance_schema.accounts:
SELECT USER, HOST, ACCOUNT_LOCKED FROM performance_schema.accounts WHERE USER = 'app_user';
实际登录时,被锁用户会收到明确报错:
ERROR 3956 (HY000): Access denied for user 'app_user'@'192.168.1.100'. Account is locked.
- 这个错误只在认证阶段抛出,不是权限拒绝(
ERROR 1045) -
performance_schema.accounts需要开启setup_consumers中的global_instrumentation,否则该表为空 - 锁定倒计时不会实时显示,只能等时间自然结束或人工解锁
全局默认值不影响已有用户,且PASSWORD_LOCK_TIME单位是分钟不是秒
全局配置用SET PERSIST写入mysqld-auto.cnf,比如:
SET PERSIST failed_login_attempts = 5; SET PERSIST password_lock_time = 2;
但这只影响后续新创建的用户(且未在CREATE USER中覆盖该参数时)。已有用户策略完全独立,靠各自的mysql.user.authentication_string元数据存储。
- 很多人误以为改了全局就“全站生效”,其实只是默认值,极易踩坑
-
PASSWORD_LOCK_TIME 1是1分钟,不是1秒;设0.0167才约等于1秒 - 锁定期间所有连接(包括localhost)都会被拒,没有例外IP白名单机制
最常被忽略的是:策略只作用于密码验证失败,不防SQL注入、不防慢查询、也不限制并发连接数——它纯粹是防暴力撞库的窄口径防护。











