我有事务复制设置。假设服务器 A 上的三个数据库复制到服务器 B 上相应的三个数据库。数据库是相同的(不同客户端的结构相同)。服务器 B 还充当分发服务器。一切正常。现在我需要更改其中一个表(这也是一篇发表文章)。我需要同时在所有数据库中执行此操作。我遵循这个过程(它是脚本化的):
- 从出版物中删除我需要修改的表格的文章
- 对我的表进行更改(必须删除并重新创建)
- 加回文章
- 生成快照(可以只为修改后的文章生成部分快照,请参阅此处的详细说明)
这是我遇到僵局的地方。执行此存储过程时,分发数据库中会发生死锁:sp_MSdrop_subscription。我没有直接调用这个过程,但显然它在我运行 sp_dropsubscription 时被执行(参见上面的步骤 #1)。再次,我同时修改了所有发布数据库,它们都使用相同的分发数据库,所以这就是问题所在。这两个冲突语句被死锁跟踪 (1222) 捕获,并且显然来自 sp_MSdrop_subscription 内部。
第一个连接运行:
if not exists (select * from dbo.MSsubscriptions where
publisher_id = @publisher_id and
publisher_db = @publisher_db and
(publication_id = @publication_id or @publication_id is NULL or @independent_agent = 0 ) and
independent_agent = @independent_agent and
subscriber_id = @subscriber_id and
subscriber_db = @subscriber_db and
subscription_type = @subscription_type)
第二个连接运行:
delete from dbo.MSsubscriptions where
publisher_id = @publisher_id and
publisher_db = @publisher_db and
(publication_id = @publication_id or
@publication_id is NULL) and
(@article_id is NULL or
article_id = @article_id) and
Message
((subscriber_id = @subscriber_id and
(subscriber_db = @subscriber_db or @subscriber_id = @virtual)) or
-- Delete virtual anonymous subscription
-- if deleting virtual subscription for a anonymous publication
(@subscriber_id = @virtual and subscriber_id = @virtual_anonymous))
这是被锁定的资源列表:
resource-list
keylock hobtid=72057594039959552 dbid=34 objectname=distribution.dbo.MSsubscriptions indexname=ucMSsubscriptions id=lock13563b300 mode=X associatedObjectId=72057594039959552
owner-list
owner id=process2d7241498 mode=X
waiter-list
waiter id=process212b58188 mode=S requestType=wait
keylock hobtid=72057594040025088 dbid=34 objectname=distribution.dbo.MSsubscriptions indexname=iMSsubscriptions id=lock17ff3af80 mode=X associatedObjectId=72057594040025088
owner-list
owner id=process212b58188 mode=X
waiter-list
waiter id=process2d7241498 mode=U requestType=wait
我感谢有关如何避免这种情况的任何指示。我现在能想到的唯一解决方法是每个发布数据库都有单独的分发数据库,但我不敢相信复制不支持同时修改多个发布者。
谢谢!
自从我个人使用复制以来已经有一段时间了,所以我不是最新的实际问题。具有多个订阅者的发布者是很常见的。但是,Microsoft 建议在您有多个发布者时使用多个分发数据库。以下帖子有方向:
http://technet.microsoft.com/en-us/library/ms183524.aspx
“但是,如果多个 Publisher 使用单个 Distributor,请考虑为每个 Publisher 创建一个分发数据库。这样做可以确保流经每个分发数据库的数据是不同的。”
这听起来像是对我的推荐。
我只是想分享我为解决此问题所做的工作,以防其他人遇到它。再一次,根本问题是由同时更改多个出版物引起的,这些出版物共享同一个分发数据库。在分析死锁跟踪报告的 Microsoft 查询代码后(参见我上面的原始帖子),我发现 MSsubscriptions 表缺少索引,所以我继续添加它:
您可以检查查询的执行计划并验证是否实际使用了该索引。
索引有帮助,但由于我必须同时对几十个出版物进行更改,所以它仍然不够。所以修复的第二部分是简单地引入随机延迟。我在我的部署脚本中添加了最多 3 分钟的延迟,这充分分散了查询以显着降低死锁的可能性(但没有完全消除死锁 :( 像这样:
我希望这在某些时候对某人有所帮助。