Stephen Wilson · Sep 5, 2016

Can MERGE Statements using an $HOROLOG global index cause a race condition?

UPDATE: Found a reason in my code why this could be occurring. Still it would be interesting to hear what people come back with.

Consider the following MERGE statement.


Produces output

^WORKDELETED(64165,366,16090404088,"64165,34201","user001")="SOME DATA"
<other sub-level nodes omitted>

^WORKDELETED(64165,366,16090404088,"64165,34202","user001")="SOME DATA"
<other sub-level nodes omitted>

Notice the $H value changes and the result is that you have duplicate entries in ^WORKDELETED. It seems to occur intermittently, which seems to suggest a race condition whereby the $H value changes mid-merge on some occasions and not on others. Note however that dataset for $H value 64165,34201 is the exact same as 64165,34202 ie. both timestamps contain the exact same data and sub-level nodes - only the $H indexes are different.

Is this a well known problem when you use MERGE statements in this way?

0 245
Discussion (1)0
Log in or sign up to continue

All subscripts will be calculated before merge command will start global merge, so looks like you hit this command several (at least 2) times within a second. Since you don't have $JOB as a subscript or data node it also could be that it's done from different processes.

On the other hand, it's considered a good code practice to assign $h to a variable somewhere at the top of the method, and use that variable instead of $h throughout the code.

Consider this code for example:

if (DAYNUM-$H>0) && (WKS>2) do ....
if (DAYNUM-$H<=0) && (WKS>2) do ....

You want to check if date is in future and do something different if it is. You would expect that only one branch of code would ever run; however in extremely rare circumstances when this code runs around midnight $h could change between first and second if statements and run both code branches, screwing up your database unpredictably.

Another good practice is to pass "current date" as method argument instead of assigning $h inside a method. This way it's much easier to test methods.