一、SQL Server对等复制冲突产生的原因
【IT专家网】在单个数据库环境下,不同应用程序对于同一张表中的同一条记录进行更改一般不会产生冲突。这主要是因为在数据库中已经实现了锁的机制,来避免这种冲突的产生。但是在异步分布式数据库环境中,每个事务独立作用于每个节点。最要命的是,在2008之前,没有用来跨越多个节点对事务进行序列化的机制。在以前的数据库版本中,主要是通过使用连阶段提交等控制机制,来避免这种冲突。但是这种机制并不是很好,因为其会影响到数据库的性能。
如上图所示,某个集团有三个服务器用来做OA系统的服务器,分别部署在三个不同的分支机构。此时,有可能A服务器所在的公司往用户表中插入一条记录,其员工编号为PR010;同时B服务器所在公司也同时往用户表中插入一条记录,员工编号也为PR010。而这个员工编号的字段在表中设置为关键字。此时就会出现冲突。在对等复制服务器中,在单个对等节点(如服务器A)上提交更改之后将检测不到冲突。但是,在复制这些更改并将其应用于其它对等节点之后(如A服务器中的数据复制到集团服务器,然后集团服务器再将其应用与服务器B),才能够检测到这些更改。在2008版本以前的数据库中,针对这种情况没有很好的处理机制。而在2008版本中则提出了一种全新的“冲突检测机制”,用来解决这个问题。
这个冲突检测机制的工作原理还是比较简单的。在对等复制中,用来将更改应用于每个节点的存储过程会基于每个已发布表中的某个隐藏列来检测冲突。这个隐藏列所存储的ID将为每个节点指定的发起方ID与行版本结合起来,实现冲突检测。在同步期间,分发代理会针对每个表执行同步过程。这些过程会应用来自其他对等节点的插入、更新和删除操作。如果某个过程在读取该隐藏列的值时检测到冲突,则数据库就会报错。通常情况下,如果发生这个冲突导致数据库错误,数据库分发代理会停止向这个节点应用所做的更改。
二、启用SQL Server对等复制冲突检测机制
通常情况下,如果多个节点服务器同时采取如下操作的话,就容易导致冲突。一是插入-插入冲突。如两个服务器冲突向同一个表中插入数据,而每个表中所有参与对等复制的行都使用某个主键值来进行唯一的标识。此时在将具有相同键值的行插入到多个节点时,就会发生插入-插入冲突。二是更新-更新冲突。如上图所示,服务器A与服务器B同时对某个表中相同的行进行更新,此时就会发生更新-更新冲突。与此类似,另外还可能发生插入-更细冲突、插入-删除冲突、更新-删除冲突、删除-删除冲突等等。在数据库设计时,如果预计到会发生如上这些冲突时,则就需要考虑启用冲突检测机制。由于默认情况下,可以在任何节点上更改数据,因此如果不采取必要措施的话,在不同节点上进行的数据更改就会发生冲突。如果在多个节点上修改了同一行,则该行传播给其他节点时可能会导致冲突,甚至会丢失更新的数据。有时候,这个后果会很严重。在数据库设计的时候,一定要充分预计到这种情况的产生。如果企业采用的数据库版本是2008的,则可以在各个节点上启用冲突检测机制,让数据库系统自动来检测这种冲突,避免不需要的麻烦。在SQLServer2008的环境下,有很多种方式可以用来启用这个冲突检测机制。
如可以通过存储过程来启用和禁用各个节点的冲突检测机制。在数据库系统中设置了sq_addpublication存储过程,只要管理员需要,就可以通过调用这个存储过程来启用某个节点的冲突检测机制。数据库管理员采用存储过程来启动或者禁止冲突检测机制,还有一个好处。即可以指定在检测到冲突的时候,分发代理是否应当停止应用所做的更改。默认情况下,使会让分发代理停止应用所做的更改。笔者的建议是,如果没有充分的必要,则不要更改这个默认值。
另外,如果数据库管理员不希望使用命令行的方式(即通过调用存储过程的方式)来管理这个冲突检测机制,在还可以通过企业管理器来实现。在“发布属性”的对话框中选择“订阅选项”页签或者通过“对等复制拓扑向导”都可以用来启动或者禁止冲突检测机制。不过采用这种形式来管理冲突检测机制,跟通过存储过程来启用,有一个缺陷。即此时数据库管理员会缺乏一种选择权。因为此时分发代理在检测到有冲突的时候自动停止应用所有的更改。而通过存储过程来启用冲突检测机制时,数据库管理员还可以选择是应用还是放弃。在管理这个冲突检测机制的时候,这一点差异数据库管理员需要心中有数。然后根据自己的需要,来选择合适的管理方式。
三、发现SQL Server对等复制冲突后的处理方式
当冲突检测机制检测到冲突后,该如何处理呢?笔者建议,最好按如下几个步骤处理。
首先数据库管理员应该配置冲突检测警报。也就是说,无论分发代理是否应用更改,数据库系统都应该向管理员或者用户发出警报,告知他们产生了冲突。在SQLServer2008中,当对等复制发生冲突时,会引发对等冲突检测警报。通常情况下,笔者都建议启用并配置这个警报,以便管理员在发生冲突时第一时间得到相关的信息。当启用警报功能后,如果发现有冲突,则数据库代理将会执行已经定义的任务或者向管理员所指定的邮箱发送电子邮件或者通过发生及时消息的方式向管理员或者用户发送警报,进行响应。同时,也可以将这些警报信息写入到Windows应用程序日志中。
其次需要考虑冲突数据的处理方式。以上只是警报,而不会对数据产生任何实质性的影响。最终对于冲突的数据要如何处理,还是要有管理员来定。在SQLServer2008数据库环境中,有两种处理方式,分别为停止应用所做的更改和继续应用所作的更改。默认情况下,数据库推荐的是停止应用所做的更改。如上面所述,无论是通过企业管理器还是通过存储过程来启用冲突检测机制,默认情况下分发代理都是会停止应用所做的更改。如果数据库管理员觉得这么做不合适的话,也可以通过允许分发代理继续应用所作的更改来再次同步节点。不过这么做的话,可能会引起一系列难以预料的问题。如此时很有可能导致数据的不一致。当出现这种情况的时候,必须在具有最高优先级的节点上手工的更新行,然后允许从该节点传播所做的更改。更改后如果拓扑中不再有发生冲突的更改,则所有节点的数据才会保持一致。所以,不在万不得已的情况下,不用采用这种处理方式。
四、对等复制冲突检测机制使用的限制
虽然SQLServer2008数据库中实现了对等复制的冲突检测机制,不过其在配置的时候也有一些限制条件。主要的限制条件有两个。一是对等复制中所有涉及到的可更新数据的节点都必须采用2008版本的数据库系统。也就是说必须要先将其他的数据库版本进行升级。二是必须要在所有的节点上都启用这个冲突检测机制。只要有一台没有启动的话,则就可能会有漏网之鱼。