电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

瀏覽:25日期:2023-07-14 18:27:58
1 前言

很多需要使用事務的場景,都只是在方法上直接添加個@Transactional注解

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

但是,你以為這真的夠了嗎?

事務如果未達到完美效果,在開發和測試階段都難以被發現,因為你難以考慮到太多意外場景。但當業務數據量發展,就可能導致大量數據不一致的問題,就會造成前人栽樹后人踩坑,需要大量人力排查解決問題和修復數據。

2 如何確認Spring事務生效了?

使用@Transactional一鍵開啟聲明式事務, 這就真的事務生效了?過于信任框架總有“意外驚喜”。來看如下案例

領域層 實體

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

領域服務

createUserError1調用private方法

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

createUserPrivate,被@Transactional注解。當傳入的用戶名包含test則拋異常,讓用戶的創建操作失敗

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

getUserCount

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

用戶接口層

調用UserService#createUserError1

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

測試結果即便用戶名不合法,用戶也能創建成功。刷新瀏覽器,多次發現有十幾個的非法用戶注冊。 @Transactional生效原則 public方法

除非特殊配置(比如使用AspectJ靜態織入實現AOP),@Transactional必須定義在public方法才生效。

因為Spring的AOP,private方法無法被代理到,自然也無法動態增強事務處理邏輯。

那簡單,把createUserPrivate方法改為public不就行了。但發現事務依舊未生效

必須通過代理過的類從外部調用目標方法

要調用增強過的方法必然是調用代理后的對象。嘗試修改UserService,注入一個self,然后再通過self實例調用標記有 @Transactional 注解的createUserPublic方法。設置斷點可以看到,self是由Spring通過CGLIB方式增強過的類:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

CGLIB通過繼承實現代理類,private方法在子類不可見,所以無法進行事務增強。而this指針代表調用對象本身,Spring不可能注入this,所以通過this訪問方法必然不是代理。把this改為self,這時即可驗證事務生效:非法的用戶注冊操作可回滾。

雖然在UserDomainService內部注入自己調用自己的createUserPublic可正確實現事務,但這不符常規。更合理的實現方式是,讓Controller直接調用之前定義的UserService的createUserPublic方法。

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

this/self/Controller調用UserDomainService

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

this自調用

無法走到Spring代理類

后兩種

調用的Spring注入的UserService,通過代理調用才有機會對createUserPublic方法進行動態增強。

推薦開發時打開Debug日志以了解Spring事務實現的細節。比如JPA數據庫訪問,開啟Debug日志:logging.level.org.springframework.orm.jpa=DEBUG

開啟日志后再比較下在UserService中this調用、Controller中通過注入的UserService Bean調用createUserPublic的區別。

很明顯,this調用因沒走代理,事務沒有在createUserPublic生效,只在Repository的save生效:

// 在UserService中通過this調用public的createUserPublic[23:04:30.748] [http-nio-45678-exec-5] [DEBUG] [o.s.orm.jpa.JpaTransactionManager:370 ] - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT[DEBUG] [o.s.orm.jpa.JpaTransactionManager :370 ] - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT//在Controller中通過注入的UserService Bean調用createUserPublic[10:10:47.750] [http-nio-45678-exec-6] [DEBUG] [o.s.orm.jpa.JpaTransactionManager :370 ] - Creating new transaction with name [org.geekbang.time.commonmistakes.transaction.demo1.UserService.createUserPublic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

這種實現在Controller里處理異常顯得繁瑣,還不如直接把createUserWrong2加@Transactional注解,然后在Controller中直接調用該方法。這既能從外部(Controller中)調用UserService方法,方法又是public的能夠被動態代理AOP增強。

小結

務必確認調用被@Transactional注解標記的方法被public修飾,并且是通過Spring注入的Bean進行調用。

但有時因沒有正確處理異常,導致事務即便生效也不一定能回滾。

2 事務生效不代表能正確回滾

AOP實現事務:使用try/catch包裹@Transactional注解的方法:

當方法出現異常并滿足一定條件,在catch里可設置事務回滾 沒有異常則直接提交事務 一定條件

只有異常傳播出了被@Transactional注解的方法,事務才能回滾。

Spring的 TransactionAspectSupport#invokeWithinTransaction 就是在處理事務。觀察源碼得知,只有捕獲到異常后才能進行后續事務處理:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

默認情況下,出現RuntimeException(非受檢異常)或Error,Spring才會回滾事務。

Spring的DefaultTransactionAttribute:

受檢異常一般是業務異常或類似另一種方法的返回值,出現這種異常可能業務還能完成,所以不會主動回滾 而Error或RuntimeException代表非預期結果,應該回滾

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

事務無法正常回滾的各種慘案 異常無法傳播出方法

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

受檢異常

注冊的同時會有一次文件讀,若讀文件失敗,希望用戶注冊的DB操作回滾。因讀文件拋的是受檢異常,createUserError2傳播出去的也是受檢異常

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

以上方法雖然避開了事務不生效的坑,但因異常處理不當,導致異常時依舊不回滾事務。

修復回滾失敗bug 1 手動設置讓當前事務處回滾態

若希望自己捕獲異常并處理,可手動設置讓當前事務處回滾態

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

查看日志,事務確定回滾。

Transactional code has requested rollback:手動請求回滾。關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

2 注解中聲明,期望所有Exception都回滾事務 突破默認不回滾受檢異常的限制

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

查看日志,提示回滾:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

該案例有DB操作、IO操作,在IO操作問題時期望DB事務也回滾,以確保邏輯一致性。 小結

由于異常處理不正確,導致雖然事務生效,但出現異常時沒回滾。Spring默認只對被@Transactional注解的方法出現RuntimeException和Error時回滾,所以若方法捕獲了異常,就需要通過手寫代碼處理事務回滾。若希望Spring針對其他異常也可回滾,可相應配置@Transactional注解的rollbackFor和noRollbackFor屬性覆蓋Spring的默認配置。

有些業務可能包含多次DB操作,不一定希望將兩次操作作為一個事務,這時就需仔細考慮事務傳播的配置。

3 事務傳播配置是否符合業務邏輯

案例

用戶注冊:會插入一個主用戶到用戶表,還會注冊一個關聯的子用戶。期望將子用戶注冊的DB操作作為一個獨立事務,即使失敗也不影響注冊主用戶的流程。

UserService:創建主、子用戶

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

SubUserService:使子用戶注冊失敗。期望子用戶注冊作為一個事務單獨回滾而不影響注冊主用戶

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

啟動調用后查看日志:事務回滾了

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

不對呀!因為運行時異常逃出被@Transactional注解的createUserWrong,Spring當然會回滾事務。若期望主方法不回滾,應捕獲子方法所拋的異常。

修正方案

把subUserService#createSubUserWithExceptionError包上catch,這樣外層主方法createUserError2就不會出現異常

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

啟動后查看日志注意到:

對createUserError2開啟異常處理 子方法因出現運行時異常,標記當前事務為回滾 主方法捕獲異常并打印create sub user error 主方法提交事務

但Controller出現一個UnexpectedRollbackException,異常描述提示最終該事務回滾了且為靜默回滾:因createUserError2本身并無異常,只不過提交后發現子方法已把當前事務設為回滾,無法完成提交。

明明無異常發生,但事務也不一定可提交因為主方法注冊主用戶的邏輯和子方法注冊子用戶的邏輯為同一事務,子邏輯標記了事務需回滾,主邏輯自然也無法提交。那么修復方式就明確了,獨立子邏輯的事務,即修正SubUserService注冊子用戶方法,為注解添加propagation = Propagation.REQUIRES_NEW設置REQUIRES_NEW事務傳播策略。即執行到該方法時開啟新事務,并掛起當前事務。創建一個新事務,若存在則暫停當前事務。類似同名的EJB事務屬性。注:實際事務暫停不會對所有事務管理器外的開箱。 這特別適于org.springframework.transaction.jta.JtaTransactionManager ,這就需要javax.transaction.TransactionManager被提供給它(這是服務器特定的標準Java EE)

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

主方法無變化,依舊需捕獲異常,防止異常外泄導致主事務回滾,重命名為createUserRight:

關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)

修正后再查看日志

Creating new transaction with name createUserRight

對createUserRight開啟主方法事務createMainUser finish創建主用戶完成Suspending current transaction, creating new transaction with name createSubUserWithExceptionRight主事務掛起,開啟新事務,即對createSubUserWithExceptionRight創建子用戶的邏輯Initiating transaction rollback子方法事務回滾Resuming suspended transaction after completion of inner transaction子方法事務完成,繼續主方法之前掛起的事務create sub user error:invalid status主方法捕獲到了子方法的異常Committing JPA transaction on EntityManager主方法的事務提交了,隨后我們在Controller里沒看到靜默回滾異常

小結

若方法涉及多次DB操作,并希望將它們作為獨立事務進行提交或回滾,即需考慮細化配置事務傳播方式,即配置@Transactional注解的Propagation屬性。

4 總結

若要針對private方法啟用事務,動態代理方式的AOP不可行,需要使用靜態織入方式的AOP,也就是在編譯期間織入事務增強代碼,可以配置Spring框架使用AspectJ來實現AOP。

以上就是關于Spring的@Transaction導致數據庫回滾全部生效問題(又刪庫跑路)的詳細內容,更多關于Spring @Transaction數據庫回滾的資料請關注好吧啦網其它相關文章!

標簽: Spring
相關文章:
主站蜘蛛池模板: 奇酷教育-Python培训|UI培训|WEB大前端培训|Unity3D培训|HTML5培训|人工智能培训|JAVA开发的教育品牌 | 六维力传感器_六分量力传感器_模腔压力传感器-南京数智微传感科技有限公司 | 超细粉碎机|超微气流磨|气流分级机|粉体改性设备|超微粉碎设备-山东埃尔派粉碎机厂家 | 上海办公室装修,写字楼装修—启鸣装饰设计工程有限公司 | 深圳法律咨询【24小时在线】深圳律师咨询免费 | 渣土车电机,太阳能跟踪器电机,蜗轮蜗杆减速电机厂家-淄博传强电机 | 拉力机-万能试验机-材料拉伸试验机-电子拉力机-拉力试验机厂家-冲击试验机-苏州皖仪实验仪器有限公司 | 瓶盖扭矩测试仪-瓶盖扭力仪-全自动扭矩仪-济南三泉中石单品站 | 空气能采暖,热泵烘干机,空气源热水机组|设备|厂家,东莞高温热泵_正旭新能源 | 税筹星_灵活用工平台_企业财务顾问_财税法薪综合服务平台 | 合肥抖音SEO网站优化-网站建设-网络推广营销公司-百度爱采购-安徽企匠科技 | 隔离变压器-伺服变压器--输入输出电抗器-深圳市德而沃电气有限公司 | 阀门智能定位器_电液动执行器_气动执行机构-赫尔法流体技术(北京)有限公司 | 金属管浮子流量计_金属转子流量计厂家-淮安润中仪表科技有限公司 | 气动|电动调节阀|球阀|蝶阀-自力式调节阀-上海渠工阀门管道工程有限公司 | 耐热钢-耐磨钢-山东聚金合金钢铸造有限公司 | YT保温材料_YT无机保温砂浆_外墙保温材料_南阳银通节能建材高新技术开发有限公司 | 液压油缸-液压站生产厂家-洛阳泰诺液压科技有限公司 | 美的商用净水器_美的直饮机_一级代理经销商_Midea租赁价格-厂家反渗透滤芯-直饮水批发品牌售后 | 开平机_纵剪机厂家_开平机生产厂家|诚信互赢-泰安瑞烨精工机械制造有限公司 | 南京技嘉环保科技有限公司-杀菌除臭剂|污水|垃圾|厕所|橡胶厂|化工厂|铸造厂除臭剂 | 铝单板_铝窗花_铝单板厂家_氟碳包柱铝单板批发价格-佛山科阳金属 | 清水-铝合金-建筑模板厂家-木模板价格-铝模板生产「五棵松」品牌 | 高清视频编码器,4K音视频编解码器,直播编码器,流媒体服务器,深圳海威视讯技术有限公司 | 同学聚会纪念册制作_毕业相册制作-成都顺时针宣传画册设计公司 | 北京康百特科技有限公司-分子蒸馏-短程分子蒸馏设备-实验室分子蒸馏设备 | 彼得逊采泥器-定深式采泥器-电动土壤采样器-土壤样品风干机-常州索奥仪器制造有限公司 | 捷码低代码平台 - 3D数字孪生_大数据可视化开发平台「免费体验」 | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | 氨水-液氨-工业氨水-氨水生产厂家-辽宁顺程化工 | 铝板冲孔网,不锈钢冲孔网,圆孔冲孔网板,鳄鱼嘴-鱼眼防滑板,盾构走道板-江拓数控冲孔网厂-河北江拓丝网有限公司 | 灰板纸、灰底白、硬纸板等纸品生产商-金泊纸业 | 桨叶搅拌机_螺旋挤压/方盒旋切造粒机厂家-无锡市鸿诚输送机械有限公司 | 船用锚链|专业锚链生产厂家|安徽亚太锚链制造有限公司 | 路面机械厂家 | 北京企业宣传片拍摄_公司宣传片制作-广告短视频制作_北京宣传片拍摄公司 | 开锐教育-学历提升-职称评定-职业资格培训-积分入户 | 消电检公司,消电检价格,北京消电检报告-北京设施检测公司-亿杰(北京)消防工程有限公司 | 【星耀裂变】_企微SCRM_任务宝_视频号分销裂变_企业微信裂变增长_私域流量_裂变营销 | 真空干燥烘箱_鼓风干燥箱 _高低温恒温恒湿试验箱_光照二氧化碳恒温培养箱-上海航佩仪器 | 低温柔性试验仪-土工布淤堵-沥青车辙试验仪-莱博特(天津)试验机有限公司 |