這個是並發情況下導致的數據庫事務錯誤,先介紹下背景。
背景
springboot+springmvc+sqlserver+mybatis
一個controller里有五六個接口,這些接口都用到了spring的事務管理,這些接口單個調用的時候都很正常,當我模擬幾十個並發請求這些接口的時候,總會有一兩次的mybatis的持久化操作會出錯,具體錯誤:
nested exception is org.apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause: java.lang.reflect.UndeclaredThrowableException ### The error may involve com.xxxxxxxxx-Inline ### The error occurred while setting parameters ### SQL: update xxxx set ccccc = ? ,jid = ? ,status = ? where bcode=? and status != 0 ### Cause: java.lang.reflect.UndeclaredThrowableException
根據提示的這個UndeclaredThrowableException,到網上搜索都是說mybatis的映射文件里的字段屬性與model里的寫的不一致。
但是如果是寫法不對的話,應該每次請求的都報錯啊,現在是幾十次里只有一兩次報錯,肯定不是這個原因。
在網上搜了半天,無果,於是把代碼放到服務器上再模擬並發測試一下,還是會有一兩次報錯,不過這次報的錯就很明朗了
### Error querying database. Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 事務(進程 ID 62)與另一個進程被死鎖在 鎖 資源上,並且已被選作死鎖犧牲品。請重新運行該事務。 ### The error may exist in file [E:\kkkkk\xxxMapper.xml] ### The error may involve com.xxxxx.ppppp ### The error occurred while handling results ### SQL: SELECT b.* FROM xxxxx a RIGHT JOIN ooooo b ON a.GId = b.id where a.bcode = '11111' ### Cause: com.microsoft.sqlserver.jdbc.SQLServerException: 事務(進程 ID 62)與另一個進程被死鎖在 鎖 資源上,並且已被選作死鎖犧牲品。請重新運行該事務。 ; SQL []; 事務(進程 ID 62)與另一個進程被死鎖在 鎖 資源上,並且已被選作死鎖犧牲品。請重新運行該事務。; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: 事務(進程 ID 62)與另一個進程被死鎖在 鎖 資源上,並且已被選作死鎖犧牲品。請重新運行該事務。
原來是並發引起的數據庫事務報錯,具體原因和修改看這篇:對於spring中事務@Transactional注解的理解
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
我了解了一下事務處理機制,原來這個錯誤是在數據庫中拋出的。因為不同線程在事務中處理相同的數據時,數據庫會采取讓一個執行而另一個放棄執行,於是就出現上面的錯了。之所以插入不容易出現這個錯誤,是因為插入的速度快,不容易出現。同時如果修改的時候按照條件修改數據速度就會慢,如果按照主鍵或索引修改速度就會快,也不容易出現這個錯誤。@xmt1139057136,雖然沒給具體的方法確實是按照這個思路想出來的,謝謝啦。對了,我對TOMCAT在局域網內進行壓力測試時,發現速度明顯比本地慢的多,而且無法處理並發1000條了(本機是可以的),向請教一下。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
解決方法
2.把事務的隔離級別改為寬松的,read_uncommited