alwaysOn為什么不支持分布式事務


Alwayson是微軟從SQL2012開始引入的一種高可用和高性能架構,它既可以實現故障轉移,同時又能實現查詢分離,是當前SQL server的所有架構中最優秀的一種。

因此,一般我們都會推薦使用AlwaysON來部署生產數據庫,不過,盡管AlwaysON的優勢非常明顯,但並非適應於所有的業務場景。

AlwaysON不支持分布式事務和跨數據庫事務

什么是分布式事務和跨數據庫事務

分布式事務是指通過分布式事務協調器(MSDTC)的統一控制、將事務中的每個操作分解到多台主機上分別執行、每台主機執行成功后整個事務才能提交的事務,分布式事務協調器用來保證數據的一致性。跨數據庫事務與此類似,只是不會用到MSDTC,而是將DBID最小的一個作為分布式事務協調器。

為什么AlwaysON不支持分布式事務

如果在一個分布式事務執行期間AlwaysON發生了故障轉移,AG服務從主副本轉移到了輔助副本,分布式事務協調器因為收不到原主副本的事務提交確認信息,認為事務執行失敗,然后將其他參與(分布式事務的)節點上的應要提交的事務回滾。對於新的主副本,因為沒有參與之前的分布式事務,因此無法從分布式事務協調器獲取事務的狀態,繼續維持現有的數據不變化,從而導致新副本與參與分布式事務的其他節點上的數據不一致。

備注:跨數據庫事務的原因與此類似。

下面我們通過圖例來展示這個過程:

下圖:假設有ABC三個節點,AC之間做了AlwaysON,其中A.table1中a的初始值為0,B.table1中a的初始值為1000。有一個分布式事務1,需要將節點A的表中a加上1000,同時需要在節點B的表中a減去1000。

BEGIN TRAN 

Update A.table1 set a=a+1000 ; 

Update B.table1 set a=a-1000 ; 

COMMIT TRAN 

正常情況下,最后的結果應該是A.table1.a=1000,B.table1.a=0,,C.table1.a=1000。

現在有這樣一個場景,A和B都已經commit,A.table1.a=1000,B.table1.a=0,且A已經將事務1的操作通過日志同步到了主機C,C.table1.a=1000。

正常情況下,主機A和B都向事務協調器發送commit ack(提交確認)信息,事務協調器收到兩者的確認信息后就可以將整個事務標記為提交。但現在A在發送commit ack信息時發生了宕機,分布式事務協調器只收到了主機B的commit ack,於是協調器將整個事務標記為失敗,然后在主機B上回滾事務1的操作,此時B.table1.a=1000。

節點C雖然接管了AlwaysON集群,因為它並不是分布式事務的執行者之一,所以它無法從分布式事務協調器獲取事務1的狀態,因此它不會回滾,a的值保持不變。最后C.table1.a=1000、B.table1.a=1000,發生了數據不一致的問題。

clip_image002

參考文章:

http://blogs.msdn.com/b/alwaysonpro/archive/2014/01/06/not-supported-ags-with-dtc-cross-database-transactions.aspx;

https://msdn.microsoft.com/en-us/library/ms366279(v=sql.110).aspx;

AlwaysON的主副本使用傳統的SQL Server故障轉移集群

從上文可以看到,AlwaysON不支持分布式事務(和跨數據庫事務)的根本原因在於主副本故障轉移到輔助副本時會造成分布式事務執行不一致。

解決這個問題的焦點就是主副本和輔助副本的故障轉移。如果主副本與輔助副本之間不允許故障轉移(也就是處於異步同步模式下),輔助副本的職責只是接受來自主副本的日志,然后執行redo實現同步,這樣一來就不會產生異常數據。

不過,主、輔副本無法故障轉移后,主副本存在單點故障的風險,為了避免此類情況發生,我們可以為主副本建立傳統的SQL Server故障轉移集群。在這種架構下,如果主節點在執行分布式事務發生了故障轉移,輔節點接管的SQL實例是原主節點的同一個實例,而且數據文件和日志文件是相同的,所以不會與其他參與分布式事務的節點產生數據不一致的問題。

clip_image004


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM