解决Hangfire启动时异常:'The Command Timeout expired before the operation completed.'

环境

Hangfire Package Version:1.8.12
Mysql Version:8.0.32

问题简介

.NET6 API项目接入了Hangfire,我使用的存储数据库是Mysql,在启动时Mysql连接抛出了'The Command Timeout expired before the operation completed.'异常信息。然后数据库操作hangfireset这张表,发现查询及增删改操作时会直接卡死无响应。最后你会发现抛出的这个异常信息就是hangfireset表操作无响应导致的。

问题解决

一:hangfireset表既无法查询也无法增删改

1、执行语句列出当前的操作process

在mysql数据库中执行show processlist;命令,展出所有的进程。正常的话你会发现如下图所示Command列为Query的行数据,然后根据Info字段找到操作hangfireset表相关的进程,可以看到操作该表的相关语句(我这里是DROP操作)。

image

2、执行命令杀死该进程

根据上图我们可以看到行对应的Id是1842,所以我们执行kill 1842;命令杀死这个进程即可。这个时候我们就可以正常查询hangfireset这张表了,但是可能增删改时仍然会导致无响应,如果你也有这个问题,请继续往下看。

二:hangfireset表可以查询但是无法增删改

1、查询正在执行的事务是否存在XA事务

导致这个问题的原因可能就是存在没有正常提交或回滚的XA事务,所以我们需要手动执行下回滚操作,那么首先执行以下语句
SELECT * FROM information_schema.INNODB_TRX;查询出有哪些正在执行的事务,执行结果如下图所示。

image

如上图所示,trx_mysql_thread_id=0的行数据就属于XA事务,可以看到trx_state一直处于RUNNING状态,但是这种进程我们无法直接使用kill命令杀死,我们可以使用下面的方法。

2、回滚XA事务

首先执行xa recover;命令查看XA事务信息,执行结果如下图所示:

image

然后我们需要根据上面查询到的数据拼接成下面的语句xa rollback 'fd096c93-f52c-4602-938e-805fcff61b1d:1663','1663', 1;
比如我查到的数据bqual_length=4,所以右边的字符我就取data的后4位1663就可以了,对应的左边的字符就取data前面剩余的。

具体的规则根据 xa rollback 'left(data,gtrid_length)','substr(data,gtrid_length+1,bqual_length)', formatID;这种格式进行拼接即可。

然后在数据库中执行该语句,再次查询该条数据会被删除也就是成功被回滚了。
再去操作hangfireset这张表,会发现已经可以正常操作了。

其他SQL记录

点击查看代码
-- 查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; 
-- 查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

参考文章记录

Mysql的表无法修改、删除等操作,卡死、锁死情况的处理办法
MySQL里trx_mysql_thread_id为0 的事务导致大量锁等待超时该咋整

至此本次分享就结束了,希望这些能帮助到您,如文中内容有误或者您有其他看法,还望在评论区指正或讨论。
END

posted @ 2024-07-03 16:26  AND1云梯  阅读(433)  评论(0)    收藏  举报