[英]Spring Transactional slows down complete process
我正在嘗試分析我有兩個班級的情況。 一類是 ProcessImpl,它是起點並在內部調用其他子事務。我不知道出了什么問題。 processImpl 正在導入一些東西並將相關數據寫入數據庫。
眼鏡
Spring-orm 版本:3.2.18.RELEASE。
JDK 版本:1.8。
Db : H2(在任何 db 上記錄相同的性能)。
問題
如果我從ProcessImpl.processStage()
刪除@Transactional
,則該過程需要約 50 秒如果我從ProcessImpl.processStage()
保留@Transactional
,則該過程需要約 15 分鍾。 不知道為什么會這樣。 長期以來,我一直試圖解決這個問題,但沒有運氣。 請看下面的代碼。
要求:完整的processStage()
應該完成或完全回滾,即使其中一個子事務失敗。
僅供參考:我也收到很多消息,例如:“參與現有交易”。 試圖通過向processStage()
添加propagation=Propagation.NESTED
來解決這個問題,但沒有奏效。
ProcessImpl 類。
public class ProcessImpl {
/*This is the big transaction that calls other transactional stuff from MyServiceImpl
* This is starting point you can say for the process...
*
* If we remove @Transactional from here the process is lightning fast
* With transactional : 15minutes
* Without transactional : 50 seconds
* */
@Transactional
public void processStage(){
MyServiceImpl mp = new MyServiceImpl();
//do some stuff
mp.doWork1();
//do more work
mp.doWork2();
}
}
MyServiceImpl 類
class MyServiceImpl{
@Transactional
public void doWork1(){
Object o = doChildWork();
// and more stuff
//calls other class services and dao layers
}
@Transactional
public void doWork2(){
//some stuff
doChildWork2();
doChildWork();
//more work
}
@Transactional
public Object doChildWork(){
return new Object(); //hypothetical, I am returning list and other collection stuff
}
@Transactional
public Object doChildWork2(){
return new Object(); //hypothetical, I am returning list and other collection stuff
}
}
另外,在這里我會遇到自調用問題,這在事務中是不可取的嗎?
很難猜測你的代碼到底發生了什么,但是這些是可能的問題:
鎖定數據庫級別。 當您在doWork1()
和doWork2()
更新相同的 DB 對象時,可能會發生這種情況。 由於這兩種方法都是一個事務中進行內部完成更新doWork1()
將不會被提交到doWork2()
完成。 這兩種方法可能會嘗試鎖定同一個 DB 對象並等待它。 從技術上講,它可以是任何 DB 對象:表中的行、索引、整個表等。
分析您的代碼並嘗試找出可能被鎖定的內容。 您還可以在方法運行時查看數據庫事務日志。 所有流行的 DB 都提供有助於查找有問題的地方的功能。
在休眠上下文刷新期間減慢速度。 如果您更新太多對象,ORM 引擎(比如 Hibernate)必須接收它們並將它們保存在內存中。 從字面上看,Hibernate 必須具有更新對象的所有舊狀態和所有新狀態。 有時它不是以最佳方式做到這一點。
您可以使用調試來指示這一點。 嘗試找到最慢的地方並檢查那里到底調用了什么。 我可能猜測它在休眠更新緩存狀態時會變慢。
還有一個問題。 我看到您在processStage()
期間使用構造函數創建了MyServiceImpl
。 我建議您通過彈簧自動裝配替換此代碼。 首先,您使用它的方式不是它設計的使用方式,但理論上這也會以某種方式影響執行。
我會遇到自調用問題,這在事務中是不可取的嗎?
不,它會很好地忽略所有注釋。 的通話doChildWork()
和doChildWork2()
內doWork2()
將被視為標准的java調用(春風不能夠任何“神奇”添加到他們,只要你直接調用它們)。
這里的任何答案實際上都只是(消息靈通的)猜想。 在這種情況下,最好的辦法是使用 Java 分析器並進行詳細的 cpu 級別分析以准確了解發生了什么。
我建議使用優秀的 YourKit,它是商業版,但您可以獲得免費試用版。
https://www.yourkit.com/docs/java/help/performance_bottlenecks.jsp
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.