SQLServer2012 Locking

  • I have a insert stored procedure that inserts data with the values passed as parameters to this proc and then call another proc that selects the same data that is inserted. I execute the insert procedure within a transaction(READ COMMITTED). I see deadlocks when multiple processes call the insert stored proc. How can I get around this? Any help is appreciated

    code:

    *create proc [dbo].[xyz_Insert]

    @FixingSource VarChar(60)

    ,@FixTime DateTime

    ,@InstrumentId Int

    ,@Lhs Decimal(18, 14)

    ,@Rhs Decimal(18, 14)

    ,@Version Int

    ,@ChangeTime DateTime

    ,@ChangeUser VarChar(60)

    as

    set nocount on

    if @Version = 0

    set @Version = 1

    insert into [TableA] ([FixingSource], [FixTime], [InstrumentId], [Lhs], [Rhs], [Version], [ChangeTime], [ChangeUser])

    values (@FixingSource, @FixTime, @InstrumentId, @Lhs, @Rhs, @Version, @ChangeTime, @ChangeUser)

    exec [dbo].[xyz_Read]

    @FixingSource = @FixingSource

    ,@FixTime = @FixTime

    ,@InstrumentId = @InstrumentId

    ----------

    CREATE proc [dbo].[XYZ_Read]

    @FixingSource VarChar(60) = null ,@FixTime DateTime = null ,@InstrumentId Int = null

    as

    set nocount on

    select *

    from [TableA]

    where (@FixingSource is null or [FixingSource] = @FixingSource)

    and (@FixTime is null or [FixTime] = @FixTime)

    and (@InstrumentId is null or [InstrumentId] = @InstrumentId)

    go*

  • To start...

    http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/

    Can you post the deadlock graph? (you can get it out of the system health extended events session)

    Also, https://www.simple-talk.com/sql/performance/sql-server-deadlocks-by-example/

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass
  • <deadlock>

    <victim-list>

    <victimProcess id="process4c430c8" />

    </victim-list>

    <process-list>

    <process id="process4c430c8" taskpriority="0" logused="348" waitresource="PAGE: 8:1:1502781 " waittime="147" ownerId="31042786" transactionname="user_transaction" lasttranstarted="2014-07-03T17:01:32.197" XDES="0x377a856a8" lockMode="S" schedulerid="18" kpid="10208" status="suspended" spid="78" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2014-07-03T17:01:32.200" lastbatchcompleted="2014-07-03T17:01:32.200" lastattention="1900-01-01T00:00:00.200" clientapp=".Net SqlClient Data Provider" hostname="WS7LDN00019343" hostpid="12856" loginname="SRVFXTP" isolationlevel="read committed (2)" xactid="31042786" currentdb="8" lockTimeout="4294967295" clientoption1="673316896" clientoption2="128056">

    <executionStack>

    <frame procname="FXTP.dbo.FixingSnapshotRepository_LimitOrderFixingSnapshot_Read" line="13" stmtstart="404" sqlhandle="0x03000800a2c1341c533f0d015da3000001000000000000000000000000000000000000000000000000000000">

    select *

    from [LimitOrderFixingSnapshot]

    where (@FixingSource is null or [FixingSource] = @FixingSource)

    and (@FixTime is null or [FixTime] = @FixTime)

    and (@InstrumentId is null or [InstrumentId] = @InstrumentId) </frame>

    <frame procname="FXTP.dbo.FixingSnapshotRepository_LimitOrderFixingSnapshot_Insert" line="17" stmtstart="1122" sqlhandle="0x03000800dbe5281d041317015da3000001000000000000000000000000000000000000000000000000000000">

    exec [dbo].[FixingSnapshotRepository_LimitOrderFixingSnapshot_Read]

    @FixingSource = @FixingSource

    ,@FixTime = @FixTime

    ,@InstrumentId = @InstrumentId </frame>

    </executionStack>

    <inputbuf>

    Proc [Database Id = 8 Object Id = 489219547] </inputbuf>

    </process>

    <process id="process2c6bc38" taskpriority="0" logused="348" waitresource="PAGE: 8:1:1502782 " waittime="171" ownerId="31042795" transactionname="user_transaction" lasttranstarted="2014-07-03T17:01:32.287" XDES="0x3780916a8" lockMode="S" schedulerid="10" kpid="5768" status="suspended" spid="77" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2014-07-03T17:01:32.293" lastbatchcompleted="2014-07-03T17:01:32.290" lastattention="1900-01-01T00:00:00.290" clientapp=".Net SqlClient Data Provider" hostname="WS7LDN00019343" hostpid="12856" loginname="SRVFXTP" isolationlevel="read committed (2)" xactid="31042795" currentdb="8" lockTimeout="4294967295" clientoption1="673316896" clientoption2="128056">

    <executionStack>

    <frame procname="FXTP.dbo.FixingSnapshotRepository_LimitOrderFixingSnapshot_Read" line="13" stmtstart="404" sqlhandle="0x03000800a2c1341c533f0d015da3000001000000000000000000000000000000000000000000000000000000">

    select *

    from [LimitOrderFixingSnapshot]

    where (@FixingSource is null or [FixingSource] = @FixingSource)

    and (@FixTime is null or [FixTime] = @FixTime)

    and (@InstrumentId is null or [InstrumentId] = @InstrumentId) </frame>

    <frame procname="FXTP.dbo.FixingSnapshotRepository_LimitOrderFixingSnapshot_Insert" line="17" stmtstart="1122" sqlhandle="0x03000800dbe5281d041317015da3000001000000000000000000000000000000000000000000000000000000">

    exec [dbo].[FixingSnapshotRepository_LimitOrderFixingSnapshot_Read]

    @FixingSource = @FixingSource

    ,@FixTime = @FixTime

    ,@InstrumentId = @InstrumentId </frame>

    </executionStack>

    <inputbuf>

    Proc [Database Id = 8 Object Id = 489219547] </inputbuf>

    </process>

    </process-list>

    <resource-list>

    <pagelock fileid="1" pageid="1502781" dbid="8" subresource="FULL" objectname="FXTP.dbo.LimitOrderFixingSnapshot" id="lock253b8c080" mode="IX" associatedObjectId="72057609976217600">

    <owner-list>

    <owner id="process2c6bc38" mode="IX" />

    </owner-list>

    <waiter-list>

    <waiter id="process4c430c8" mode="S" requestType="wait" />

    </waiter-list>

    </pagelock>

    <pagelock fileid="1" pageid="1502782" dbid="8" subresource="FULL" objectname="FXTP.dbo.LimitOrderFixingSnapshot" id="lock2b2cfd680" mode="SIX" associatedObjectId="72057609976217600">

    <owner-list>

    <owner id="process4c430c8" mode="SIX" />

    </owner-list>

    <waiter-list>

    <waiter id="process2c6bc38" mode="S" requestType="wait" />

    </waiter-list>

    </pagelock>

    </resource-list>

    </deadlock>

  • There is only one index - clustered index. The primary key is made of 3 colums FixingSource, FixTime, InstrumentID.

  • No doubt Gail will fix your problem more elegantly, but here is one idea (untested). In your script:

    1) Define a temp table with the same structure as TableA.

    2) Call the insert proc, with a modified INSERT clause to include an OUTPUT to the temp table you just created.

    3) Modify your read proc to read from the temp table rather than TableA.

    4) Drop the temp table - if you're feeling tidy 🙂

    If you haven't even tried to resolve your issue, please don't expect the hard-working volunteers here to waste their time providing links to answers which you could easily have found yourself.

  • 1) You simply MUST fix the IS NULL OR construct - and do so EVERYWHERE you have it in your code.

    2) On the whole I would say that many tables, of more than a few rows anyway, can probably benefit from having at least one non-clustered index on them on something that is "searched/linked" that isn't the clustered index.

    3) Non-clustered indexes are one of the main points of attack for resolving deadlock issues. Here's an oldy-but-goodie: http://blogs.msdn.com/bartd/archive/2006/09/09/Deadlock-Troubleshooting_2C00_-Part-1.aspx

    Note there are 2 additional parts to this blog series.

    Also note that Extended Events can offer a VERY good window into deadlock information.

    Best,
    Kevin G. Boles
    SQL Server Consultant
    SQL MVP 2007-2012
    TheSQLGuru on googles mail service

  • Hi I have modified the query as directed. The filters in the query are on the columns that are part of the clustered index (primary key) so I am not sure if I can do anything further to fine tune the Indexes. I see the same behaviour even if I add a non-clusterd-covering index... Please help.

    CREATE proc [dbo].[XYZ_Read]

    @FixingSource VarChar(60) = null ,@FixTime DateTime = null ,@InstrumentId Int = null

    as

    set nocount on

    select *

    from [LimitOrderFixingSnapshot]

    where ([FixingSource] = CASE WHEN @FixingSource IS NULL THEN [FixingSource] ELSE @FixingSource END)

    AND ([FixTime] = CASE WHEN @FixTime IS NULL THEN [FixTime] ELSE @FixTime END)

    AND ([InstrumentId] = CASE WHEN @InstrumentId IS NULL THEN [InstrumentId] ELSE @InstrumentId END)

  • neltonk (7/7/2014)


    Hi I have modified the query as directed. The filters in the query are on the columns that are part of the clustered index (primary key) so I am not sure if I can do anything further to fine tune the Indexes. I see the same behaviour even if I add a non-clusterd-covering index... Please help.

    CREATE proc [dbo].[XYZ_Read]

    @FixingSource VarChar(60) = null ,@FixTime DateTime = null ,@InstrumentId Int = null

    as

    set nocount on

    select *

    from [LimitOrderFixingSnapshot]

    where ([FixingSource] = CASE WHEN @FixingSource IS NULL THEN [FixingSource] ELSE @FixingSource END)

    AND ([FixTime] = CASE WHEN @FixTime IS NULL THEN [FixTime] ELSE @FixTime END)

    AND ([InstrumentId] = CASE WHEN @InstrumentId IS NULL THEN [InstrumentId] ELSE @InstrumentId END)

    Did you take the time to read the link which Gail posted regarding catch-all queries?

    If you haven't even tried to resolve your issue, please don't expect the hard-working volunteers here to waste their time providing links to answers which you could easily have found yourself.

  • neltonk (7/7/2014)


    Hi I have modified the query as directed. The filters in the query are on the columns that are part of the clustered index (primary key) so I am not sure if I can do anything further to fine tune the Indexes. I see the same behaviour even if I add a non-clusterd-covering index... Please help.

    CREATE proc [dbo].[XYZ_Read]

    @FixingSource VarChar(60) = null ,@FixTime DateTime = null ,@InstrumentId Int = null

    as

    set nocount on

    select *

    from [LimitOrderFixingSnapshot]

    where ([FixingSource] = CASE WHEN @FixingSource IS NULL THEN [FixingSource] ELSE @FixingSource END)

    AND ([FixTime] = CASE WHEN @FixTime IS NULL THEN [FixTime] ELSE @FixTime END)

    AND ([InstrumentId] = CASE WHEN @InstrumentId IS NULL THEN [InstrumentId] ELSE @InstrumentId END)

    As Phil's post implies, your solution did absolutely nothing to remove the IS NULL or problem.

    Best,
    Kevin G. Boles
    SQL Server Consultant
    SQL MVP 2007-2012
    TheSQLGuru on googles mail service

  • Given the situation where we had to put a hot fix asap... This worked brilliantly. We have now time to fine tune the code.

    I will now try using the recompile hint / dynamic sql within the code as suggested by Gail and test the impact.

    Thanks for your help.

  • TSQLLearner2014 (7/7/2014)


    Given the situation where we had to put a hot fix asap... This worked brilliantly. We have now time to fine tune the code.

    I will now try using the recompile hint / dynamic sql within the code as suggested by Gail and test the impact.

    Thanks for your help.

    I promise you your CODE did NOT make things "brilliantly faster"!! The simple fact that the sproc was compiled and the next call got you the most-often-fast-plan was what happened. Your IS NULL OR could do the same thing - be fast SOME (or even most) of the time.

    Glad to hear you have time to put in a proper fix!!

    Best,
    Kevin G. Boles
    SQL Server Consultant
    SQL MVP 2007-2012
    TheSQLGuru on googles mail service

  • TheSQLGuru (7/7/2014)


    TSQLLearner2014 (7/7/2014)


    Given the situation where we had to put a hot fix asap... This worked brilliantly. We have now time to fine tune the code.

    I will now try using the recompile hint / dynamic sql within the code as suggested by Gail and test the impact.

    Thanks for your help.

    I promise you your CODE did NOT make things "brilliantly faster"!!

    What that change would have done is make the performance consistent. Consistently not great, but consistent.

    Gail Shaw
    Microsoft Certified Master: SQL Server, MVP, M.Sc (Comp Sci)
    SQL In The Wild: Discussions on DB performance with occasional diversions into recoverability

    We walk in the dark places no others will enter
    We stand on the bridge and no one may pass

Viewing 12 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic. Login to reply