Note that there are some explanatory texts on larger screens.

plurals
  1. POSELECT COUNT(SomeId) with INSERT later to same SomeId: Appropriate locking strategy?
    primarykey
    data
    text
    <p>I am using SQL Server 2012. I have a repeatable read transaction where I perform this query:</p> <pre><code>select count(SomeId) from dbo.MyTable where SomeId = @SomeId </code></pre> <p><code>SomeId</code> is a column whose value may repeat in the table (think foreign key). However, <code>SomeId</code> is not a member of any index nor is it a foreign key.</p> <p>Later in the transaction, I insert a record into <code>dbo.MyTable</code> with the same <code>@SomeId</code>, thus changing what the <code>select count(*)</code> would return were I to run it again:</p> <pre><code>insert into dbo.MyTable (SomeId, ...) values (@SomeId, ...) </code></pre> <p>Several threads in my application can execute this transaction at the same time. Because of this, I'm getting deadlocks on the <code>insert</code> statement. At first, I thought an <code>updlock</code> would be appropriate on the <code>select</code> statement, but I quickly realized that it wouldn't work because I'm not actually updating the rows selected by the <code>select count(SomeId)</code>.</p> <p>My question is this: is there any way to avoid a potentially expensive table lock? Is there any way to lock just rows that involve <code>SomeId</code>, even if they haven't been inserted yet (strange, I know)? I want to force other threads to wait while the original transaction completes its work but I don't want to lock rows unnecessarily.</p> <p><strong>EDIT</strong></p> <p>Here's what I'm trying to accomplish:</p> <p>I only want to insert up to eight rows for a particular <code>SomeId</code>. There are several unrelated processes that can start one of these transactions, potentially at the same time. The <code>select count</code> detects whether there are already eight rows and causes the operation to fail for that process. If the count is less than eight, that same transaction performs additional work, then inserts a record at the end, thus effectively incrementing the count were the <code>select count</code> to be run again. I am hitting the deadlock on the <code>insert</code> statement.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload