日常Bug排查-拋異常不回滾
前言
日常Bug排查系列都是一些簡單Bug排查,筆者將在這裡介紹一些排查Bug的簡單技巧,同時順便積累素材_。
Bug現場
最近有人反映java應用運算元據庫的時候,拋異常不回滾。這還了得,不過筆者篤定肯定是用法的鍋,不然就全亂套了。所以筆者去Review他的程式碼。
程式碼片段
@Transacion(value="x")
public void s1() throw MyException{
update(1);
throwBusinessException();
update(2);
}
乍看上去沒啥問題。
思路
筆者用@Transaction註解也用了好幾年了,從來沒遇到過拋異常不回滾的情況。看他的用法也和筆者差不多呀?
然後筆者稍微思索了會,發現我寫的程式碼和出問題的這一段稍稍有些不一樣。我是這麼寫的:
@Transacion(value="transManager")
public void s1(){
update(1);
update(2);
}
貌似我從來沒有在函式上加過throw MyException,難道是這段有問題?
翻看MyException程式碼,發現它僅僅繼承了Exception。
class MyEception extends Exception {
}
好像就這點不一樣。而筆者自定義的Exception基本繼承了RuntimeException的。
翻下Spring原始碼
按照這個思路,筆者去翻了下Spring的原始碼,看下它在宣告式事務中的處理邏輯到底是什麼,於是翻到了這一段處理事務異常的程式碼:
TransactionAspectSupport.java
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
if (txInfo.transactionAttribute.rollbackOn(ex)) {
}else{
// We don't roll back on this exception.
// Will still roll back if TransactionStatus.isRollbackOnly() is true.
// 在checkedException的時候,不會被rollBack,會commit!!!
}
}
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
看程式碼邏輯就明白了,只有異常繼承RuntimeException或者Error的時候才會回滾!
好了,讓業務開發改了下程式碼,問題解決了。
總結
遇到問題時,找到出問題程式碼段和類似的正確程式碼段的不同處,以此為切入,往往能抓住線索。