MySQL 8.0中授予KILL权限需同时授予CONNECTION_ADMIN和PROCESS动态权限且必须全局授予ON .,仅授其一或host不匹配均导致ERROR 1227或静默失败,授权后须重新登录生效。

权限不足:CONNECTION_ADMIN 和 PROCESS 缺一不可
MySQL 8.0 中 KILL 命令不再依赖 SUPER 或隐式权限,必须显式授予两个动态权限:CONNECTION_ADMIN(发 KILL 命令)和 PROCESS(查看线程 ID)。只给其中一个,KILL 会静默失败或报 ERROR 1227 (42000): Access denied。
常见错误操作:
- 执行
GRANT KILL ON *.* TO 'u'@'h';→ 语法合法但无实际效果,MySQL 8.0 已移除该静态权限别名 - 只授
CONNECTION_ADMIN→ 能执行KILL 123,但SHOW PROCESSLIST报错,无法定位目标线程 - 只授
PROCESS→ 可见线程,但执行KILL时直接拒绝
正确授权方式(注意 host 必须完全匹配):
GRANT CONNECTION_ADMIN ON *.* TO 'monitor'@'10.20.%'; GRANT PROCESS ON *.* TO 'monitor'@'10.20.%'; FLUSH PRIVILEGES; -- 这步对动态权限无效,可省略
授权后需用该用户重新登录才生效。
host 匹配失败:CURRENT_USER() 决定权限校验依据
KILL 是否成功,不看 USER()(登录来源),而取决于 CURRENT_USER() 返回的账号 host 部分是否与授权时的 host 完全一致。哪怕网络层能通,只要 host 字符串不等,权限就判为缺失。
典型陷阱:
- 你用
'monitor'@'10.20.5.10'登录,但只授了'monitor'@'10.20.%'→ 成功 - 你用
'monitor'@'localhost'登录,但只授了'monitor'@'127.0.0.1'→ 失败(localhost在 MySQL 中走 socket,不等价于127.0.0.1) - 被杀目标是
'app'@'localhost',而你的监控账号没单独授'monitor'@'localhost'→ 即使你当前连接能查到它,KILL仍可能无反应
验证方式:
SELECT CURRENT_USER(), USER();
确保 CURRENT_USER() 输出与 SHOW GRANTS FOR ... 中的 host 段严格一致。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
KILL 执行后显示 Killed 但连接未断:线程处于清理等待状态
执行 KILL connection_id 后,SHOW PROCESSLIST 中对应行的 Command 列变为 Killed,不代表立即退出——这是正常中间态。MySQL 会设置线程内部标志位,并尝试唤醒其处理终止逻辑,但需等待当前操作完成(如释放锁、回滚事务、清空临时表等)。
此时线程卡住的常见原因:
- 持有
Metadata Lock(元数据锁):例如正在 ALTER 表,其他线程阻塞在Waiting for table metadata lock,KILL 后需等 DDL 完成才能释放锁并退出 - 长事务未提交:事务中已修改大量数据,回滚耗时长;
KILL触发回滚,但你看到的是“卡在 Killed” - 写入磁盘慢:如
innodb_flush_log_at_trx_commit=1+ 磁盘 I/O 延迟高,回滚日志刷盘慢 - 执行复杂排序或临时表:
Creating sort index或Copying to tmp table状态下,KILL 信号会被延迟响应
观察手段:
SELECT THREAD_ID, PROCESSLIST_ID, PROCESSLIST_STATE, PROCESSLIST_INFO FROM performance_schema.threads WHERE PROCESSLIST_ID = 123;
若 PROCESSLIST_STATE 长时间非 NULL 或 Idle,说明仍在清理。
中间件或服务层拦截:KILL 请求根本没到 MySQL
很多生产环境部署了 ProxySQL、MaxScale、ShardingSphere 或云厂商 RDS 代理层。这些组件可能:
- 默认过滤或禁止转发
KILL类命令(安全策略) - 将客户端 IP 映射为固定后端用户(如统一用
proxy_user连接 MySQL),导致你实际以'proxy_user'@'10.0.0.1'身份操作,但权限只给了'monitor'@'10.20.%' - 启用了
require_secure_transport=ON,而你的 KILL 连接走的是非加密通道,被代理拒绝或降级处理 - 认证插件不兼容:比如用
caching_sha2_password登录代理,但 MySQL 后端配置了sha256_password,权限系统行为异常
排查顺序建议:
- 先直连 MySQL 实例(绕过所有中间件),用相同账号复现
KILL行为 - 检查代理日志是否有
deny、filtered、access denied关键词 - 确认 MySQL 错误日志(
/var/log/mysqld.log)里有无Access denied记录,且来源 IP 与你预期一致
真正棘手的不是权限没给,而是权限给了、命令发了、MySQL 也收了,但线程卡在不可中断的内核态或存储引擎层 —— 这时候只能等,或重启实例(最后手段)。










