今天在項目中,遇到了棘手的問題,在跟第三方通信過程中,本來好好的,突然就接收不到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,釋放獨占鎖。