SQL Server Deadlock – Changing Two Publications Simultaneously

deadlocksql servertransactional-replication

I have transactional replication setup. Let's say three databases on server A replicate to corresponding three databases on Server B. The databases are identical (same structure for different clients). Server B also acts as a distributor. Everything is working fine. Now I need to change one of the tables (which is also a publication article). I need to do it in all databases at the same time. I follow this process (it is scripted):

  1. Drop article for the table I need to modify from the publication
  2. Make the change to my table (it has to be dropped and re-created)
  3. Add article back
  4. Generate snapshot (it possible to have partial snapshot for just the modified article, see good explanation here)

This is where I run into deadlocks. The deadlock takes place in the distribution database when this stored procedure is executed: sp_MSdrop_subscription. I don't call this procedure directly, but apparently it gets executed when I run sp_dropsubscription (see step #1 above). Once again, I modify all publication databases at the same time and they all use the same distribution database, so this is where the problem lies. The two conflicting statements are captured by the deadlock trace (1222) and apparently come from inside sp_MSdrop_subscription.

First connection runs:

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)

Second connection runs:

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))

and here is the resource list of what's being locked:

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

I appreciate any pointers on how to avoid this. The only work-around I can think of right now is to have separate distribution databases per publication database, but I can't believe that replication doesn't support modifying multiple publishers at the same time.

Thank you!

Best Answer

It has been quite a while since I personally used replication, so I am not current on practical problems. A publisher with multiple subscribers is pretty common. However, Microsoft suggests using multiple Distribution databases when you have multiple Publishers. The following post has direction:

http://technet.microsoft.com/en-us/library/ms183524.aspx

"However, if multiple Publishers use a single Distributor, consider creating a distribution database for each Publisher. Doing so ensures that the data flowing through each distribution database is distinct."

It sounds like a recommendation to me.