* GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。

一、引言
作为一名数据库从业者,我在日常工作中经常会遇到一个棘手的问题:如何在保证安全的前提下,让业务团队拥有足够的权限去管理数据库执行的 SQL,尤其是终止那些失控的慢查询或异常线程?这个问题看似简单,却牵涉到权限设计、安全合规以及数据库稳定性等多方面的权衡。今天,我们就来聊聊 MySQL 8.0 如何通过权限体系的革新,特别是对 KILL 权限的细化支持,解决了这一痛点,并为 DBA 和业务开发团队带来了更大的灵活性。
二、从痛点说起:KILL SQL 的权限困境
在 MySQL 实际使用中,业务开发人员常希望拥有终止 SQL 的能力。例如,慢查询占用大量资源,或未优化的批量操作导致负载飙升,此时及时 KILL 问题 SQL 是最直接的解决办法。然而,MySQL 的权限设计限制让这一需求难以实现,开发人员往往只能依赖 DBA 操作,既低效又拖延响应。
在 MySQL 的传统版本(比如 5.7 及更早版本)中,KILL 权限的实现存在以下几个问题:
执行用户限制 默认情况下,用户只能 KILL 自己创建的线程。若业务程序使用统一账号(如 app_user),开发人员想通过此账号终止 SQL,必须知道其密码并登录数据库执行 KILL。然而,企业安全规范通常禁止程序账号单点登录,因其权限过大(至少包括增删改查),导致开发人员无法直接操作。这形成了一个"权限死结":想 KILL 无权限,有权限却无法登录。 SUPER 权限过大 为突破上述限制,允许用户 KILL 其他用户的 SQL,需授予 SUPER 权限。这看似可行,但 SUPER 权限是个“大杀器”:持有者不仅能 KILL 任何线程,还可修改全局参数(如 innodb_buffer_pool_size
)、执行 STOP GROUP_REPLICATION
关闭组复制等操作(甚至会导致中断服务)。此权限通常仅限超级管理员使用,对业务开发而言明显过大,且存在严重安全隐患,DBA 自然不愿授予业务团队。
面对这样的困境,我们不禁会问:难道就没有一个两全其美的办法,既能让业务团队有 KILL SQL 的能力,又不至于权限失控吗?
答案是肯定的,MySQL 8.0 的到来,让这一需求成为了现实。
三、MySQL 8.0 的细粒度权限拆分:KILL 权限独立登场
MySQL 8.0 在权限体系上迎来重大改进,最显著的是对 SUPER 权限的拆分。在 5.7 及之前,SUPER 权限如同一个大包袱,功能过于庞杂。而 8.0 引入了动态权限(即运行时可分配的细化权限),将 SUPER 拆解为多个细粒度权限,其具体内容如下:
权限名 解释 影响的部分MySQL5.7命令示例 SYSTEM_VARIABLES_ADMIN 允许在运行时更改全局系统变量,包括使用 SET GLOBAL 和 SET PERSIST,以及更改全局事务特性。 SET GLOBAL innodb_buffer_pool_size = 268435456;
SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SESSION_VARIABLES_ADMIN 允许设置需要特殊权限的受限会话系统变量。 SET SESSION sql_log_bin = 0;
REPLICATION_SLAVE_ADMIN 允许启动和停止常规复制,使用 CHANGE REPLICATION SOURCE TO、CHANGE MASTER TO 等语句。 CHANGE MASTER TO MASTER_HOST='replica_host';
GROUP_REPLICATION_ADMIN 允许启动和停止组复制(Group Replication)。 START GROUP_REPLICATION;
BINLOG_ADMIN 允许通过 PURGE BINARY LOGS 和 BINLOG 语句控制二进制日志。 PURGE BINARY LOGS TO 'mysql-bin.000010';
SET_USER_ID 允许在视图或存储程序的 DEFINER 属性中指定任何账户作为有效授权 ID。 CREATE DEFINER='admin'@'[localhost](http://localhost)' VIEW v1 AS ...;
CONNECTION_ADMIN 控制客户端连接行为,包括终止其他账户线程、绕过连接限制、离线模式连接和读写操作等。 KILL 12345; ENCRYPTION_KEY_ADMIN 启用 InnoDB 加密密钥轮换。 (无直接命令,通常涉及加密相关配置) VERSION_TOKEN_ADMIN 允许执行版本令牌(Version Tokens)功能。 (涉及特定插件,如 version_tokens_lock() 函数) ROLE_ADMIN 允许授予和撤销角色、使用 WITH ADMIN OPTION 和 ROLES_GRAPHML() 函数。 (MySQL5.7 没有 role 功能,不涉及)
SUPER 被拆分为 10 个动态权限。同时,MySQL 8.0 因新增功能和组件,又引入了 29 个动态权限,构成以下 39 个动态权限列表:
权限 级别 解释 是否为 SUPER 拆出 APPLICATION_PASSWORD_ADMIN 全局 启用双密码管理。
AUDIT_ABORT_EXEMPT 全局 允许审计日志过滤器阻止的查询继续执行。
AUDIT_ADMIN 全局 启用审计日志配置。
AUTHENTICATION_POLICY_ADMIN 全局 启用认证策略管理。
BACKUP_ADMIN 全局 启用备份管理。
BINLOG_ADMIN 全局 启用二进制日志控制。 是 BINLOG_ENCRYPTION_ADMIN 全局 启用二进制日志加密的激活和停用。
CLONE_ADMIN 全局 启用克隆管理。
CONNECTION_ADMIN 全局 启用连接限制/控制。 是 ENCRYPTION_KEY_ADMIN 全局 启用 InnoDB 密钥轮换。 是 FIREWALL_ADMIN 全局 启用防火墙规则管理(任何用户)。
FIREWALL_EXEMPT 全局 豁免用户免受防火墙限制。
FIREWALL_USER 全局 启用防火墙规则管理(自身)。
FLUSH_OPTIMIZER_COSTS 全局 启用优化器成本重新加载。
FLUSH_STATUS 全局 启用状态指示器刷新。
FLUSH_TABLES 全局 启用表刷新。
FLUSH_USER_RESOURCES 全局 启用用户资源刷新。
GROUP_REPLICATION_ADMIN 全局 启用组复制控制。 是 INNODB_REDO_LOG_ARCHIVE 全局 启用重做日志归档管理。
INNODB_REDO_LOG_ENABLE 全局 启用或禁用重做日志记录。
NDB_STORED_USER 全局 启用在 SQL 节点间共享用户或角色(NDB 集群)。
PASSWORDLESS_USER_ADMIN 全局 启用无密码用户账户管理。
PERSIST_RO_VARIABLES_ADMIN 全局 启用持久化只读系统变量。
REPLICATION_APPLIER 全局 作为复制通道的 PRIVILEGE_CHECKS_USER 角色。
REPLICATION_SLAVE_ADMIN 全局 启用常规复制控制。 是 RESOURCE_GROUP_ADMIN 全局 启用资源组管理。
RESOURCE_GROUP_USER 全局 启用资源组管理(用户级别)。
ROLE_ADMIN 全局 启用角色授予或撤销,使用 WITH ADMIN OPTION。 是 SESSION_VARIABLES_ADMIN 全局 启用设置受限会话系统变量。 是 SET_USER_ID 全局 启用设置非自身 DEFINER 值。 是 SHOW_ROUTINE 全局 启用访问存储过程定义。
SKIP_QUERY_REWRITE 全局 不重写此用户执行的查询。
SYSTEM_USER 全局 将账户指定为系统账户。
SYSTEM_VARIABLES_ADMIN 全局 启用修改或持久化全局系统变量。 是 TABLE_ENCRYPTION_ADMIN 全局 启用覆盖默认加密设置。
TELEMETRY_LOG_ADMIN 全局 启用 HeatWave on AWS 的遥测日志配置。
TP_CONNECTION_ADMIN 全局 启用线程池连接管理。
VERSION_TOKEN_ADMIN 全局 启用版本令牌函数的使用。 是 XA_RECOVER_ADMIN 全局 启用 XA RECOVER 执行。
其中,KILL SQL 可以使用 CONNECTION_ADMIN
这个动态权限来单独授权。
SUPER 因权限过大的安全隐患,在 8.0 版本开始已经不建议使用。官方文档明确指出,SUPER 已被标记为即将废弃,推荐尽早迁移至动态权限体系。

具体到 KILL SQL 的场景,还有一些细节要注意,如果开发或业务 DBA 需要 KILL SQL,除了需要刚才讨论的 CONNECTION_ADMIN
权限外,还有一个前提,要求能看到对应的线程,这要求授予 PROCESS
权限,这样他执行 show processlist
时就可以看到所有用户运行的线程了,而非只能看到自己的线程。这个权限 5.7、8.0 通用,允许用户查看其他用户的线程,授权如下:
GRANT PROCESS ON *.* TO 'dev_admin';
注意,PROCESS 权限允许查看他人 SQL 原文,可能导致敏感信息泄露。建议业务部门自行评估安全风险,例如仅授权高级业务 DBA 查看全局 SHOW PROCESSLIST
并执行 KILL SQL。
拥有 PROCESS 权限的用户可按以下步骤终止问题线程:
执行 SHOW PROCESSLIST;
查看运行线程列表,找到目标线程 ID。( 对应 PROCESS
权限 ) 执行 KILL <thread_id>;
终止指定线程。( 对应CONNECTION_ADMIN
权限 ) 例如:
SHOW PROCESSLIST;
KILL 12345;
这样一来,业务团队就拥有了终止任意 SQL 的能力,而 DBA 也不必担心他们会误操作全局参数或关闭服务器。权限控制变得更加精细,安全性和灵活性得到了兼顾。
四、系统线程的安全防护:SYSTEM_USER 权限的加持
然而,细心的读者可能会提出一个问题:如果用户拥有了 PROCESS 权限,他们会不会一不小心 KILL 掉一些关键的系统线程,比如主从复制线程(Replication Thread)或后台维护线程?这确实是一个合理的担忧,因为系统线程一旦被误杀,可能会导致数据库服务中断,甚至引发数据不一致的风险。
MySQL 8.0 的设计者显然也考虑到了这一点。为了保护系统线程,他们引入了 SYSTEM_USER 权限。这个权限的作用是区分普通用户线程和系统线程,并为后者提供额外的保护。具体规则如下:
如果某个线程是由具有 SYSTEM_USER 权限的用户创建的(通常是 MySQL 的内置系统账号,比如复制线程的执行用户),那么普通用户(没有 SYSTEM_USER 权限)无法通过 KILL 命令终止它。 只有当前会话也具备 SYSTEM_USER 权限的用户,才能 KILL 掉同样具备 SYSTEM_USER 权限的线程。
这意味着,即便业务用户拥有了 CONNECTION_ADMIN 权限,他们也无法干扰数据库的后台线程,比如主从复制线程、事件调度线程(Event Scheduler)或管理员的命令行。这种设计极大地提升了系统的稳定性,避免了权限滥用带来的潜在风险。
这就保证了普通用户无法越界操作,系统的核心功能得到了保护。
五、实战演练:如何优雅地使用 KILL 权限
1. 使用 dbops 搭建一主两从的 MySQL8.0.41 实例
dbops 是什么,见 http://dbops.cn
2. 创建程序账号 app_user,授予业务库 app_db 的增删改查权限
create user app_user identified by 'Dbops@2025';
grant select,insert,update,delete on `app\_db`.* to app_user;
3. 创建业务库、业务表,并执行长事务


4. 创建开发主管账号 dev_admin,授予查看全局 SQL 和 KILL SQL 权限
create user 'dev_admin' identified by 'Dbops@2025';
GRANT PROCESS ON *.* TO 'dev_admin';
GRANT CONNECTION_ADMIN ON *.* TO 'dev_admin';
5. 为后台线程账号(如 admin、repl)授予 SYSTEM_USER 权限,标记为受保护线程,普通用户无法 KILL
GRANT SYSTEM_USER on *.* to admin@'127.0.0.1';
GRANT SYSTEM_USER on *.* to admin@'localhost';
GRANT SYSTEM_USER on *.* to repl@'1%';
随后,重启复制线程,重新连接admin命令行窗口,让权限生效。
6. 测试 KILL SQL
受 SYSTEM_USER 保护的线程无法被终止。

而普通用户(如 app_user)的线程可被终止。

注意事项
在 MySQL 8.0 中,权限不足的错误信息因操作而异。例如,修改全局变量时:
mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation
这明确指出所需权限。
但对于 KILL SQL,若缺少 CONNECTION_ADMIN
权限,错误信息却不同:
mysql> kill 66;
ERROR 1094 (HY000): Unknown thread id: 66
此提示具有误导性,无法区分是用户未被授予 CONNECTION_ADMIN
,还是目标线程受 SYSTEM_USER
保护所致,测试时这两方面都可以注意一下。
六、总结与展望
MySQL 8.0 的细粒度权限体系,特别是动态权限的引入,有效缓解了传统版本“权限过大或过小”的困境。通过单独授予 CONNECTION_ADMIN
和 PROCESS
权限,业务团队无需 SUPER 权限即可安全管理异常 SQL 线程。而 SYSTEM_USER
权限则为系统核心线程提供了可靠保护,避免误操作导致服务中断。
dbops 默认创建 admin@'127.0.0.1'、admin@'localhost'、repl@'1%' 等账号。
欢迎讨论:是否在 dbops 1.10 新版本中支持 MySQL 8.4.x 尝鲜,默认为此三账号添加 SYSTEM_USER 权限,以进一步提升系统安全性?
参考:
https://dev.mysql.com/doc/refman/8.0/en/grant.html
https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html

一、引言

作为一名数据库从业者,我在日常工作中经常会遇到一个棘手的问题:如何在保证安全的前提下,让业务团队拥有足够的权限去管理数据库执行的 SQL,尤其是终止那些失控的慢查询或异常线程?这个问题看似简单,却牵涉到权限设计、安全合规以及数据库稳定性等多方面的权衡。今天,我们就来聊聊 MySQL 8.0 如何通过权限体系的革新,特别是对 KILL 权限的细化支持,解决了这一痛点,并为 DBA 和业务开发团队带来了更大的灵活性。
二、从痛点说起:KILL SQL 的权限困境
在 MySQL 实际使用中,业务开发人员常希望拥有终止 SQL 的能力。例如,慢查询占用大量资源,或未优化的批量操作导致负载飙升,此时及时 KILL 问题 SQL 是最直接的解决办法。然而,MySQL 的权限设计限制让这一需求难以实现,开发人员往往只能依赖 DBA 操作,既低效又拖延响应。
在 MySQL 的传统版本(比如 5.7 及更早版本)中,KILL 权限的实现存在以下几个问题:
执行用户限制 默认情况下,用户只能 KILL 自己创建的线程。若业务程序使用统一账号(如 app_user),开发人员想通过此账号终止 SQL,必须知道其密码并登录数据库执行 KILL。然而,企业安全规范通常禁止程序账号单点登录,因其权限过大(至少包括增删改查),导致开发人员无法直接操作。这形成了一个"权限死结":想 KILL 无权限,有权限却无法登录。 SUPER 权限过大 为突破上述限制,允许用户 KILL 其他用户的 SQL,需授予 SUPER 权限。这看似可行,但 SUPER 权限是个“大杀器”:持有者不仅能 KILL 任何线程,还可修改全局参数(如 innodb_buffer_pool_size
)、执行STOP GROUP_REPLICATION
关闭组复制等操作(甚至会导致中断服务)。此权限通常仅限超级管理员使用,对业务开发而言明显过大,且存在严重安全隐患,DBA 自然不愿授予业务团队。
面对这样的困境,我们不禁会问:难道就没有一个两全其美的办法,既能让业务团队有 KILL SQL 的能力,又不至于权限失控吗?
答案是肯定的,MySQL 8.0 的到来,让这一需求成为了现实。
三、MySQL 8.0 的细粒度权限拆分:KILL 权限独立登场
MySQL 8.0 在权限体系上迎来重大改进,最显著的是对 SUPER 权限的拆分。在 5.7 及之前,SUPER 权限如同一个大包袱,功能过于庞杂。而 8.0 引入了动态权限(即运行时可分配的细化权限),将 SUPER 拆解为多个细粒度权限,其具体内容如下:
权限名 | 解释 | 影响的部分MySQL5.7命令示例 |
---|---|---|
SET GLOBAL innodb_buffer_pool_size = 268435456; SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ; | ||
SET SESSION sql_log_bin = 0; | ||
CHANGE MASTER TO MASTER_HOST='replica_host'; | ||
START GROUP_REPLICATION; | ||
PURGE BINARY LOGS TO 'mysql-bin.000010'; | ||
CREATE DEFINER='admin'@'[localhost](http://localhost)' VIEW v1 AS ...; | ||
SUPER 被拆分为 10 个动态权限。同时,MySQL 8.0 因新增功能和组件,又引入了 29 个动态权限,构成以下 39 个动态权限列表:
其中,KILL SQL 可以使用 CONNECTION_ADMIN
这个动态权限来单独授权。
SUPER 因权限过大的安全隐患,在 8.0 版本开始已经不建议使用。官方文档明确指出,SUPER 已被标记为即将废弃,推荐尽早迁移至动态权限体系。

具体到 KILL SQL 的场景,还有一些细节要注意,如果开发或业务 DBA 需要 KILL SQL,除了需要刚才讨论的 CONNECTION_ADMIN
权限外,还有一个前提,要求能看到对应的线程,这要求授予 PROCESS
权限,这样他执行 show processlist
时就可以看到所有用户运行的线程了,而非只能看到自己的线程。这个权限 5.7、8.0 通用,允许用户查看其他用户的线程,授权如下:
GRANT PROCESS ON *.* TO 'dev_admin';
注意,PROCESS 权限允许查看他人 SQL 原文,可能导致敏感信息泄露。建议业务部门自行评估安全风险,例如仅授权高级业务 DBA 查看全局
SHOW PROCESSLIST
并执行 KILL SQL。
拥有 PROCESS 权限的用户可按以下步骤终止问题线程:
执行 SHOW PROCESSLIST;
查看运行线程列表,找到目标线程 ID。( 对应PROCESS
权限 )执行 KILL <thread_id>;
终止指定线程。( 对应CONNECTION_ADMIN
权限 ) 例如:
SHOW PROCESSLIST;
KILL 12345;
这样一来,业务团队就拥有了终止任意 SQL 的能力,而 DBA 也不必担心他们会误操作全局参数或关闭服务器。权限控制变得更加精细,安全性和灵活性得到了兼顾。
四、系统线程的安全防护:SYSTEM_USER 权限的加持
然而,细心的读者可能会提出一个问题:如果用户拥有了 PROCESS 权限,他们会不会一不小心 KILL 掉一些关键的系统线程,比如主从复制线程(Replication Thread)或后台维护线程?这确实是一个合理的担忧,因为系统线程一旦被误杀,可能会导致数据库服务中断,甚至引发数据不一致的风险。
MySQL 8.0 的设计者显然也考虑到了这一点。为了保护系统线程,他们引入了 SYSTEM_USER 权限。这个权限的作用是区分普通用户线程和系统线程,并为后者提供额外的保护。具体规则如下:
如果某个线程是由具有 SYSTEM_USER 权限的用户创建的(通常是 MySQL 的内置系统账号,比如复制线程的执行用户),那么普通用户(没有 SYSTEM_USER 权限)无法通过 KILL 命令终止它。 只有当前会话也具备 SYSTEM_USER 权限的用户,才能 KILL 掉同样具备 SYSTEM_USER 权限的线程。
这意味着,即便业务用户拥有了 CONNECTION_ADMIN 权限,他们也无法干扰数据库的后台线程,比如主从复制线程、事件调度线程(Event Scheduler)或管理员的命令行。这种设计极大地提升了系统的稳定性,避免了权限滥用带来的潜在风险。
这就保证了普通用户无法越界操作,系统的核心功能得到了保护。
五、实战演练:如何优雅地使用 KILL 权限
1. 使用 dbops 搭建一主两从的 MySQL8.0.41 实例
dbops 是什么,见 http://dbops.cn
2. 创建程序账号 app_user,授予业务库 app_db 的增删改查权限
create user app_user identified by 'Dbops@2025';
grant select,insert,update,delete on `app\_db`.* to app_user;
3. 创建业务库、业务表,并执行长事务


4. 创建开发主管账号 dev_admin,授予查看全局 SQL 和 KILL SQL 权限
create user 'dev_admin' identified by 'Dbops@2025';
GRANT PROCESS ON *.* TO 'dev_admin';
GRANT CONNECTION_ADMIN ON *.* TO 'dev_admin';
5. 为后台线程账号(如 admin、repl)授予 SYSTEM_USER 权限,标记为受保护线程,普通用户无法 KILL
GRANT SYSTEM_USER on *.* to admin@'127.0.0.1';
GRANT SYSTEM_USER on *.* to admin@'localhost';
GRANT SYSTEM_USER on *.* to repl@'1%';
随后,重启复制线程,重新连接admin命令行窗口,让权限生效。
6. 测试 KILL SQL
受 SYSTEM_USER 保护的线程无法被终止。

而普通用户(如 app_user)的线程可被终止。

注意事项
在 MySQL 8.0 中,权限不足的错误信息因操作而异。例如,修改全局变量时:
mysql> SET GLOBAL TRANSACTION ISOLATION LEVEL REPEATABLE READ;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) for this operation
这明确指出所需权限。
但对于 KILL SQL,若缺少 CONNECTION_ADMIN
权限,错误信息却不同:
mysql> kill 66;
ERROR 1094 (HY000): Unknown thread id: 66
此提示具有误导性,无法区分是用户未被授予 CONNECTION_ADMIN
,还是目标线程受 SYSTEM_USER
保护所致,测试时这两方面都可以注意一下。
六、总结与展望
MySQL 8.0 的细粒度权限体系,特别是动态权限的引入,有效缓解了传统版本“权限过大或过小”的困境。通过单独授予 CONNECTION_ADMIN
和 PROCESS
权限,业务团队无需 SUPER 权限即可安全管理异常 SQL 线程。而 SYSTEM_USER
权限则为系统核心线程提供了可靠保护,避免误操作导致服务中断。
dbops 默认创建 admin@'127.0.0.1'、admin@'localhost'、repl@'1%' 等账号。
欢迎讨论:是否在 dbops 1.10 新版本中支持 MySQL 8.4.x 尝鲜,默认为此三账号添加 SYSTEM_USER 权限,以进一步提升系统安全性?
参考:
https://dev.mysql.com/doc/refman/8.0/en/grant.html
https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html