日常Bug排查-拋異常不回滾

Al發表於2021-06-07

日常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的時候才會回滾!
好了,讓業務開發改了下程式碼,問題解決了。

總結

遇到問題時,找到出問題程式碼段和類似的正確程式碼段的不同處,以此為切入,往往能抓住線索。

相關文章