BizTalk - Receive Port reading twice from DB

家住魔仙堡 提交于 2019-12-04 12:22:12

The quick answer is that you have two options to fix this problem:

  1. Fix your stored procedure so that is behaves correctly in concurrent situations.
  2. Place your SQL polling receive handler within a clustered BizTalk host.

Below is an explanation of what is going on, and under that I give details of implementations to fix the issue:

Explanation

This is due to the way BizTalk receive locations work when running on multiple host instances (that is, that the receive handler for the adapter specified in the receive location is running on a host that has multiple host instances).

In this situation both of the host instances will run their receive handler.

This is usually not a problem - most of the receive adapters can manage this and give you the behaviour you would expect. For example, the file adapter places a lock on files while they are being read, preventing double reads.

The main place where this is a problem is exactly what you are seeing - when a polling SQL receive location is hitting a stored procedure. In this case BizTalk has no option other than to trust the SQL procedure to give the correct results.

It is hard to tell without seeing your procedure, but the way you are querying your records is not guaranteeing unique reads.

Perhaps you have something like:

Select * From Record 
Where Status = 'Unread'

Update Record 
Set Status = 'Read'
Where Status = 'Unread'

The above procedure can give duplicate records because between the select and the update, another call of the select is able to sneak in and select the records that have not been updated yet.

Implementing a solution

Fixing the procedure

One simple fix to the procedure is to update with a unique id first:

Update Record 
Set UpdateId = @@SPID, Status = 'Reading'
Where Status = 'Unread'

Select * From Record
Where UpdateId = @@SPID
And Status = 'Reading'

Update Record
Set Status = 'Read'
Where UpdateId = @@SPID
And Status = 'Reading'

@@SPID should be unique, but if it proves not to be you could use newid()

Using a clustered host

Within the BizTalk server admin console when creating a new host it is possible to specify that that host is clustered. Details on doing this are in this post by Kent Weare.

Essentially you create a host as normal, with host instances on each server, then right click the host and select cluster.

You then create a SQL receive handler for the polling that works under that host and use this handler in your receive location.

A BizTalk clustered host ensures that all items that are members of that host will run on one and only one host instance at a time. This will include your SQL receive location, so you will not have any chance of race conditions when calling your procedure.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!