暂无图片
暂无图片
8
暂无图片
暂无图片
3
暂无图片

MySQL 线程Killed状态解读

原创 CuiHulong 2024-08-30
893

介绍

在MySQL中,当对某个进程执行Kill命令时,通过SHOW PROCESSLIST,在进程状态中会显示Killed情况。一般这个Killed状态是短暂的。但在某些情况下,Kill线程可能仍需要一些时间才能终止。如果该线程被其他线程锁定,则一旦其他线程释放其锁,Kill就会生效。
在MySQL中,Kill命令可以选择Connection 或 Query对象:

  • Connection 在终止连接正在执行的任何语句后,它终止与给定processlist_id关联的连接。
  • Query终止连接当前正在执行的语句,但保持连接本身不变。

Kill语句返回而不等待确认,但Kill标志检查会在相当短的时间内中止操作。中止操作以执行任何必要的清理也需要一些时间。当Kill线程进入处理状态,就会处于Killed状态,对于线程语句如以下处理方式:

  • 对于SELECT操作期间,对于ORDER BY和GROUP BY循环,在读取行块后检查标记。如果设置了Kill标志,则语句将中止。
  • 对于表执行ALTER TABLE操作会定期检查从原始表读取的每几行复制的终止标志。如果设置了Kill标志,则中止语句并删除临时表。(清理可能需要一些时间)
  • 对于UPDATE或DELETE操作期间,每次读取块后以及每次更新或删除行后都会检查终止标志。如果设置了Kill标志,则语句将中止。如果不使用事务,则更改不会回滚。(清理可能需要一些时间)
  • GET_LOCK()中止并返回NULL。
  • 如果线程处于表锁处理程序中(状态:Locked),则表锁将迅速中止。
  • 如果线程在写调用中等待可用磁盘空间,则写操作将中止,并显示“磁盘已满”错误消息。
  • 对于EXPLAIN ANALYZE语句,中止并打印第一行输出。这在MySQL 8.0.20及更高版本中有效。
  • 对于MyISAM表上,对于REPAIR TABLE或OPTIMIZE TABLE操作会导致表损坏且无法使用。(清理可能需要一些时间)

其实在MySQL客户段,常用的Ctrl + C操作就是 Kill Query操作,和手动执行kill query <query_id> 的效果是一样的。通过General日志记录,可以确认。
image.png

线程处于killed状态

对于一些长时间处于Killed状态的语句,通过SHOW PROCESSLIST查看。如下场景:

mysql> show processlist; +------+-----------------+-----------+-----------+---------+------+----------------------------+------------------+ | Id | User | Host | db | Command | Time | State | Info | +------+-----------------+-----------+-----------+---------+------+----------------------------+------------------+ | 11 | event_scheduler | localhost | NULL | Daemon | 6912 | waiting for handler commit | NULL | | 34 | root | localhost | db1 | Killed | 320 | System lock | load data infile '/tmp/emp.sql' | | 5804 | root | localhost | employees | Query | 0 | init | show processlist | +------+-----------------+-----------+-----------+---------+------+----------------------------+------------------+ 3 rows in set (0.00 sec)
复制

也可以通过提供的视图去看执行情况:

#更改行trx_rows_modified指标,进行等待数值变成0 mysql> SELECT * FROM information_schema.INNODB_TRX\G *************************** 1. row *************************** trx_id: 407928 trx_state: RUNNING trx_started: 2024-08-25 10:26:37 trx_requested_lock_id: NULL trx_wait_started: NULL trx_weight: 2 trx_mysql_thread_id: 0 trx_query: load data infile '/tmp/emp.sql' trx_operation_state: NULL trx_tables_in_use: 0 trx_tables_locked: 1 trx_lock_structs: 1 trx_lock_memory_bytes: 11281123 trx_rows_locked: 234343432 trx_rows_modified: 9928343 trx_concurrency_tickets: 0 trx_isolation_level: REPEATABLE READ trx_unique_checks: 1 trx_foreign_key_checks: 1 trx_last_foreign_key_error: NULL trx_adaptive_hash_latched: 0 trx_adaptive_hash_timeout: 0 trx_is_read_only: 0 trx_autocommit_non_locking: 0 trx_schedule_weight: NULL #TRANSACTIONS事务堵塞情况: mysql> SHOW ENGINE INNODB STATUS\G
复制

对于执行时间过长,无法等待,需要在操作系统层面直接Kill -9 mysqld进程(慎用)。之后重新启动MySQL服务。

  • 这时MySQL可能会进行Rollback操作 或 Commit操作。(绝大情况下都会进行Rollbackup)。
  • 最好的办法就是等待InnoDB自己将事务进行回滚。
  • 除此之外,也可以写入配置参数innodb_force_recovery=3不执行事务回滚操作(慎用)。

注意事项

  • 大事务Kill操作需要很长时间,因为有进行回滚。有可能30分钟 或 几个小时。
  • Kill connection操作会先断开网络连接,然后客户端会重新在一个线程发送Kill Query命令,show processlist会将kill connection的状态显示为Killed。然而其实InnoDB可能因为io繁忙,锁等待,并发线程数不够,而没有机会终止当前线程。出现这种情况,及时要腾出系统资源,比如IO,终止掉其他线程,增大innodb_thread_concurrency, 然后等待线程执行完毕。
  • 并行读取参数innodb_parallel_read_threads当大于1,有可能会导致hang住线程(Bug).可以改成1.再观察
  • 第三方备份软件xtrabackup终止一些语句 或 FTWRL命令导致hang住情况(Bug)。

总结

目前MySQL的Killed状态就像网上说的是“不死金身”。所以kill操作要谨慎使用。当使用Kill语句时,要关注这个线程情况。

如果出现长时间Killed状态,可以二次执行Kill命令,如还存在无法马上结束的情况,最快速的解决办法就是重启MySQL。因为有可能会导致底层数据页损坏,要有从节点提升主的准备。

此外,还应定期检查数据库的性能和资源使用情况,以便及时发现并解决问题。

参考

https://dev.mysql.com/doc/refman/8.4/en/general-thread-states.html
https://zhuanlan.zhihu.com/p/382578875
https://cloud.tencent.com/developer/article/1857161

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

筱悦星辰
暂无图片
6月前
评论
暂无图片 0
做善良的人,行善良的事,那些我们传递的温暖,也终将温暖我们。
6月前
暂无图片 点赞
评论
鲁鲁
暂无图片
7月前
评论
暂无图片 0
MySQL 线程Killed状态解读
7月前
暂无图片 点赞
评论
雪狼sunny
暂无图片
7月前
评论
暂无图片 0
MySQL 线程Killed状态解读
7月前
暂无图片 点赞
评论