azure sql database – AzureSql/sql server – Concurrent transactions, readlock and updatelock

I have a transaction where

1. Transaction start
 2. I run an update on a row with a given id that is marked currently active and mark it inactive
 3. Add a new row with a audit_id from the above updated row
 4. Commit the transaction.

However, when two concurrent transactions ran, ended up with a scenario where #2 happened twice on the same row and #3 got executed twice resulting in two extra rows being inserted instead of just 1.

TLDR; No two rows should have same audit ids. If transactions ran as intended, row 3 should have never appeared.

id x_id is_active audit_id. status
1.  1     false.    null     inprogress
2.  1     true       1        done
3.  1     true       1        done

How do I avoid this?
I was looking at ROWLOCKS, UPDATELOCKS and HOLDLOCKs

For the above scenario, looks like I need a HOLDLOCK..

1.Transaction begin
 2. Select id from tableA where x_id = 1 and is_active = true and status = inprogress with (HOLDLOCK)
 3. update is_active = false where id = (id from #2)
 4. Insert into tableA x_id=1, is_active = true, audit_id = (id from #2), status = done
 5. Commit transaction

Is the above right? According to what I understand,
If I use UPDLOCK, say in another concurrent transaction #2 was already executed, both transactions will end up executing #3, not at once but one after the other in overlapping transactions and I’ll end up with two rows having same audit_id and status = done.

Read more here: Source link