MySQL原生权限系统不支持时间限制,需通过定时修改mysql.user表的account_locked字段并执行FLUSH PRIVILEGES来实现;兼容性方案为cron调用SQL脚本,高阶方案是用ProxySQL代理层基于active字段动态控制连接。

MySQL 用户访问时间限制不能靠原生权限系统实现
MySQL 的 GRANT 和 REVOKE 机制不支持按时间窗口(比如“只允许工作日 9:00–18:00 登录”)动态开关权限。所谓“时间限制”,必须由外部调度 + 权限变更组合完成,本质是定时开关账号的登录能力。
用 mysql.user 表 + FLUSH PRIVILEGES 手动禁用/启用账号
这是最直接、兼容性最好的方式:修改 account_locked 字段或清空 password_expired 状态,并强制刷新权限缓存。
- 锁定用户(禁止登录):
UPDATE mysql.user SET account_locked = 'Y' WHERE User = 'app_user' AND Host = '192.168.1.%'; FLUSH PRIVILEGES;
- 解锁用户(恢复登录):
UPDATE mysql.user SET account_locked = 'N' WHERE User = 'app_user' AND Host = '192.168.1.%'; FLUSH PRIVILEGES;
- 注意:
account_locked在 MySQL 5.7.6+ 才可用;老版本只能用SET PASSWORD FOR 'u'@'h' = ''配合REQUIRE NONE临时废密,但不推荐——会干扰密码策略和审计日志 - 执行前务必确认
sql_mode不含STRICT_TRANS_TABLES,否则UPDATE mysql.user可能报错
Linux 定时任务(cron)驱动权限变更
把上面的 SQL 封装成 shell 脚本,用系统级 cron 控制执行时机,是最轻量、无需额外服务的方案。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 写一个脚本
/opt/mysql-timer/lock_user.sh,内容为:mysql -u root -p'xxx' -e "UPDATE mysql.user SET account_locked = 'Y' WHERE User='app_user'; FLUSH PRIVILEGES;"
- 在
crontab -e中添加两行:0 9 * * 1-5 /opt/mysql-timer/unlock_user.sh
0 18 * * 1-5 /opt/mysql-timer/lock_user.sh
(表示周一至五早 9 点解锁、晚 6 点锁定) - 关键点:MySQL root 密码不能硬编码在脚本里,应使用
~/.my.cnf配置文件并设chmod 600;否则ps aux可见明文密码 - 测试 cron 时加
2>&1 | logger -t mysql-timer把输出记入系统日志,避免静默失败
替代方案:用代理层(如 ProxySQL)做连接时间过滤
如果业务已部署 ProxySQL 或计划引入流量网关,可在代理侧拦截非授权时段的连接请求,比改 MySQL 权限更灵活、无重启风险。
- ProxySQL 支持基于
mysql_users表的active字段 + 自定义 scheduler 脚本控制开关 - 优势:不触碰 MySQL 内核表,不影响主从复制,可做更细粒度控制(例如只限某类 SQL 时间段)
- 坑点:ProxySQL 的 scheduler 默认每 10 秒轮询一次,无法做到秒级精度;且所有客户端必须走代理,直连 MySQL 的连接不受控
- 验证是否生效:查
stats_mysql_connection_pool表中对应用户的ConnUsed是否归零,而非只看 MySQL 的processlist
实际落地时,多数团队卡在权限变更后没执行 FLUSH PRIVILEGES,或者 cron 脚本里 MySQL 客户端找不到配置文件路径。时间策略越复杂,越建议用 ProxySQL 这类有状态代理,而不是反复 patch 数据库元数据。










