本篇文章討論在數(shù)據(jù)庫(kù)讀寫(xiě)分離時(shí)使用事務(wù)的那些坑:
1. 在讀寫(xiě)分離時(shí)會(huì)不會(huì)造成事務(wù)主從切換錯(cuò)誤
一個(gè)線(xiàn)程在Serivcie時(shí)Select時(shí)選擇的是從庫(kù),DynamicDataSourceHolder中ThreadLocal對(duì)應(yīng)線(xiàn)程存儲(chǔ)的是slave,然后調(diào)用Manager時(shí)進(jìn)入事務(wù),事務(wù)使用默認(rèn)的transacatinManager關(guān)聯(lián)的dataSource,而此時(shí)會(huì)不會(huì)獲取到的是slave?

經(jīng)驗(yàn)證不會(huì),但這是因?yàn)樵贏OP設(shè)置動(dòng)態(tài)織出的時(shí)候,都要清空DynamicDataSourceHolder的ThreadLocal,如此避免了數(shù)據(jù)庫(kù)事務(wù)傳播行為影響的主從切換錯(cuò)誤。如果Selelct DB從庫(kù)完成之后不清空ThreadLocal,那么ThreadLocal跟線(xiàn)程綁定就會(huì)傳播到Transaction,造成事務(wù)操作從庫(kù)異常。而清空ThreadLocal之后,Spring的事務(wù)攔截先于動(dòng)態(tài)數(shù)據(jù)源的判斷,所以事務(wù)會(huì)切換成主庫(kù),即使事務(wù)中再有查詢(xún)從庫(kù)的操作,也不會(huì)造成主庫(kù)事務(wù)異常。
2. 事務(wù)隔離級(jí)別和傳播特性會(huì)不會(huì)影響數(shù)據(jù)連接池死鎖
一個(gè)線(xiàn)程在Service層Select數(shù)據(jù)會(huì)從數(shù)據(jù)庫(kù)獲取一個(gè)Connection,通常來(lái)講,后續(xù)DB的操作在同一線(xiàn)線(xiàn)程會(huì)復(fù)用這個(gè)DB Connection,但是從Service進(jìn)入Manager的事務(wù)后,Get Seq獲取全局唯一標(biāo)識(shí),所以Get Seq一般都會(huì)開(kāi)啟新的事物從DB Pool里重新獲取一個(gè)新連接進(jìn)行操作,但是問(wèn)題是如果兩個(gè)事務(wù)關(guān)聯(lián)的datasource是同一個(gè),即DB Pool是同一個(gè),那么如果DB Pool已經(jīng)為空,是否會(huì)造成死鎖?

經(jīng)驗(yàn)證會(huì)死鎖,所以在實(shí)踐過(guò)程中,如果有此實(shí)現(xiàn),建議Get Seq不要使用與事務(wù)同一個(gè)連接池。或者采用事務(wù)隔離級(jí)別設(shè)置PROPAGATION_REQUIRES_NEW進(jìn)行處理。最優(yōu)的實(shí)踐是宎把Get SeqId放到事務(wù)里處理。
總結(jié)
分析的不是很深,有很多地方還不是特別了解,歡迎吐槽相互學(xué)習(xí),尤其是說(shuō)錯(cuò)了的地方,一定請(qǐng)幫忙指正,以免誤人子弟。
原文地址:http://www.linkedkeeper.com/detail/blog.action?bid=1043
本文受原創(chuàng)保護(hù),未經(jīng)作者授權(quán),禁止轉(zhuǎn)載。 linkedkeeper.com (文/張松然)