1. 程式人生 > >記一次資料庫事務問題的定位與解決

記一次資料庫事務問題的定位與解決

技術背景:SpringBoot用SpringMVC + + +的MyBatis的ActiveMQ

問題描述:在服務層中根據主鍵對某表中資料記錄的部分欄位進行更新,更新之後使用ActiveMQ的對剛才更新資料的中另外一個欄位進行更新,訊息佇列的更新是後加的,加上之後導致先前的更新失效;

 

問題分析:經過日誌分析,訊息佇列觸發的更新總是拿到服務層中第一次更新前的資料進行更新,所以會將第一次更新的結果進行覆蓋因為該服務層中的方法加了事務且設定回滾異常為exception.class。資料庫使用的MySQL的,因此隔離級別是可重複讀,預設的事務傳播級方式是必需的。也就是說訊息佇列中查詢到的資料是第一次更新後尚未提交的資料。原因是在訊息佇列中訊息傳送後,方法返回後事務才會提交。

修改方案:

1)將事務的隔離級別設定為最高的序列化級別,這個級別的事務是寫讀都不會並行的,在第一次更新沒有提交之前訊息佇列中消費者的更新操作是不能進行的,只有等待,也就能解決上述問題;

2)將訊息佇列中消費者對資料的更新操作使用aop在atfterReturn之後進行;

3)對於訊息佇列中消費者對資料的更新只更新本更新要更新的欄位,避免覆蓋前者的更新結果;

方案對比:

方案1程式碼修改量少,但是序列化級別的隔離將會導致併發效能大大降低,不可取;

方法2程式碼量多,但是基本不用修改別處程式碼,風險小;

方案3程式碼量少,只需要修改消費者的處理邏輯即可,在不熟悉業務的前提下風險大。

綜上,方案3是最優的解決方案。

總結:資料庫的更新,最後只更新本次更新的欄位,否則會造成不必要的問題;