Alwayson是微軟從SQL2012開始引入的一種高可用和高性能架構,它既能夠實現故障轉移,同時又能實現查詢分離,是當前SQL server的全部架構中最優秀的一種。sql
所以,通常咱們都會推薦使用AlwaysON來部署生產數據庫,不過,儘管AlwaysON的優點很是明顯,但並不是適應於全部的業務場景。數據庫
分佈式事務是指經過分佈式事務協調器(MSDTC)的統一控制、將事務中的每一個操做分解到多臺主機上分別執行、每臺主機執行成功後整個事務才能提交的事務,分佈式事務協調器用來保證數據的一致性。跨數據庫事務與此相似,只是不會用到MSDTC,而是將DBID最小的一個做爲分佈式事務協調器。架構
若是在一個分佈式事務執行期間AlwaysON發生了故障轉移,AG服務從主副本轉移到了輔助副本,分佈式事務協調器由於收不到原主副本的事務提交確認信息,認爲事務執行失敗,而後將其餘參與(分佈式事務的)節點上的應要提交的事務回滾。對於新的主副本,由於沒有參與以前的分佈式事務,所以沒法從分佈式事務協調器獲取事務的狀態,繼續維持現有的數據不變化,從而致使新副本與參與分佈式事務的其餘節點上的數據不一致。異步
備註:跨數據庫事務的緣由與此相似。分佈式
下面咱們經過圖例來展現這個過程:性能
下圖:假設有ABC三個節點,AC之間作了AlwaysON,其中A.table1中a的初始值爲0,B.table1中a的初始值爲1000。有一個分佈式事務1,須要將節點A的表中a加上1000,同時須要在節點B的表中a減去1000。spa
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。server
正常狀況下,主機A和B都向事務協調器發送commit ack(提交確認)信息,事務協調器收到二者的確認信息後就能夠將整個事務標記爲提交。但如今A在發送commit ack信息時發生了宕機,分佈式事務協調器只收到了主機B的commit ack,因而協調器將整個事務標記爲失敗,而後在主機B上回滾事務1的操做,此時B.table1.a=1000。blog
節點C雖然接管了AlwaysON集羣,由於它並非分佈式事務的執行者之一,因此它沒法從分佈式事務協調器獲取事務1的狀態,所以它不會回滾,a的值保持不變。最後C.table1.a=1000、B.table1.a=1000,發生了數據不一致的問題。
參考文章:
https://msdn.microsoft.com/en-us/library/ms366279(v=sql.110).aspx;
從上文能夠看到,AlwaysON不支持分佈式事務(和跨數據庫事務)的根本緣由在於主副本故障轉移到輔助副本時會形成分佈式事務執行不一致。
解決這個問題的焦點就是主副本和輔助副本的故障轉移。若是主副本與輔助副本之間不容許故障轉移(也就是處於異步同步模式下),輔助副本的職責只是接受來自主副本的日誌,而後執行redo實現同步,這樣一來就不會產生異常數據。
不過,主、輔副本沒法故障轉移後,主副本存在單點故障的風險,爲了不此類狀況發生,咱們能夠爲主副本創建傳統的SQL Server故障轉移集羣。在這種架構下,若是主節點在執行分佈式事務發生了故障轉移,輔節點接管的SQL實例是原主節點的同一個實例,並且數據文件和日誌文件是相同的,因此不會與其餘參與分佈式事務的節點產生數據不一致的問題。