今天在项目中,遇到了棘手的问题,在跟第三方通信过程中,本来好好的,突然就接收不到tcp发来的数据了。重启之后正常。
第一感觉,当然是怀疑第三方的问题,毕竟自己写的代码是亲生的。而且自己的架构也十分简单,接收数据,操作数据库,回复包而已。
接收到的任何数据都会第一时间打日志,既然没有日志,当然是第三方没有发送啦! 可是第三方有5个客户端,同时都接收不到数据,自己写的代码问题明显嫌疑度急剧上升。
通过查看日志,发现在接收不到数据之前有大量的业务失败日志(检测器心跳失败)。由此怀疑是不是检测器心跳失败造成的线程堵死,等到每个线程都堵死了,自然就接收
不到数据了。然后翻看业务代码。大概的处理是这样的
update ***
if(sqlfail)
{
rollback
return false;
}
select***
if(sqlfail)
{
rollback
return false;
}
if(!next)
{
return false;
}
update***
...
commit
通过模拟数据执行sql,发现是select查询的是空数据然后return false返回的,导致update造成的独占锁一直没有释放。
好家伙,那别的线程凡是处理到这张表统统堵死,慢慢的导致全部线程堵死啦,哈哈,再也接收不到数据了。
经验教训:在业务逻辑复杂的函数里,如果先前有update/insert/delete 等修改表的操作,在异常退出的时候一定要记得commit或rollback,释放独占锁。
|