alwaysOn为何不支持分布式事务

Alwayson是微软从SQL2012开始引入的一种高可用和高性能架构,它既能够实现故障转移,同时又能实现查询分离,是当前SQL server的全部架构中最优秀的一种。sql

所以,通常咱们都会推荐使用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。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,发生了数据不一致的问题。

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

相关文章
相关标签/搜索