0

RC分離レベルでトランザクションを実行しているプロセスが、別のテーブルですでにselectステートメントを実行している場合、なぜIXページロックを保持するのでしょうか。つまり、ステートメントが終了するとロックが解放されると思いました(そのため、繰り返し不可能な読み取りが発生する可能性があります)。

デッドロックxmlは次のとおりです。

<deadlock-list>
 <deadlock victim="process5cd048">
  <process-list>
   <process id="process5cd048" taskpriority="0" logused="10000" waittime="2220" schedulerid="3" kpid="5764" status="suspended" spid="62" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-11-09T12:16:52.730" lastbatchcompleted="2012-11-09T12:16:52.730" lastattention="2012-11-08T17:33:28.597" clientapp=".Net SqlClient Data Provider" hostname="CWCEINAW" hostpid="4908" loginname="cwcuser" isolationlevel="read committed (2)" xactid="1157173773" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="adhoc" line="1" sqlhandle="0x020000005b3f1719cc3b4ad87e96487fe7fbf624ab5c2984">
SELECT * FROM WP_CashCenter_StockTransactionLine
                    WHERE [StockTransaction_id] IN (
                        SELECT DISTINCT [ST].[id]
                        FROM WP_CashCenter_StockTransaction AS [ST]
                            LEFT JOIN WP_CashCenter_StockTransactionLine AS [STL] ON ([STL].[StockTransaction_id] = [ST].[id])
                        WHERE [ST].[Type] IN (1, 0, 10, 9)
AND ([STL].[Direction] IN (1, 0) OR [STL].[id] IS NULL) 
AND [ST].[Status] IN (0, 1)
AND ([STL].[StockContainer_id] = 3000080311 OR [ST].[StockContainerID] = 3000080311))     </frame>
    </executionStack>
    <inputbuf>
SELECT * FROM WP_CashCenter_StockTransactionLine
                    WHERE [StockTransaction_id] IN (
                        SELECT DISTINCT [ST].[id]
                        FROM WP_CashCenter_StockTransaction AS [ST]
                            LEFT JOIN WP_CashCenter_StockTransactionLine AS [STL] ON ([STL].[StockTransaction_id] = [ST].[id])
                        WHERE [ST].[Type] IN (1, 0, 10, 9)
AND ([STL].[Direction] IN (1, 0) OR [STL].[id] IS NULL) 
AND [ST].[Status] IN (0, 1)
AND ([STL].[StockContainer_id] = 3000080311 OR [ST].[StockContainerID] = 3000080311))    </inputbuf>
   </process>
   <process id="process33ebc8" taskpriority="0" logused="10676" waitresource="PAGE: 5:1:1144344" waittime="2221" ownerId="1157173773" transactionname="user_transaction" lasttranstarted="2012-11-09T12:16:52.197" XDES="0x41518b140" lockMode="S" schedulerid="5" kpid="5272" status="suspended" spid="62" sbid="0" ecid="9" priority="0" trancount="0" lastbatchstarted="2012-11-09T12:16:52.730" lastbatchcompleted="2012-11-09T12:16:52.730" clientapp=".Net SqlClient Data Provider" hostname="CWCEINAW" hostpid="4908" isolationlevel="read committed (2)" xactid="1157173773" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="adhoc" line="1" sqlhandle="0x020000005b3f1719cc3b4ad87e96487fe7fbf624ab5c2984">
SELECT * FROM WP_CashCenter_StockTransactionLine
                    WHERE [StockTransaction_id] IN (
                        SELECT DISTINCT [ST].[id]
                        FROM WP_CashCenter_StockTransaction AS [ST]
                            LEFT JOIN WP_CashCenter_StockTransactionLine AS [STL] ON ([STL].[StockTransaction_id] = [ST].[id])
                        WHERE [ST].[Type] IN (1, 0, 10, 9)
AND ([STL].[Direction] IN (1, 0) OR [STL].[id] IS NULL) 
AND [ST].[Status] IN (0, 1)
AND ([STL].[StockContainer_id] = 3000080311 OR [ST].[StockContainerID] = 3000080311))     </frame>
    </executionStack>
    <inputbuf>
    </inputbuf>
   </process>
   <process id="process4e13048" taskpriority="0" logused="11448" waitresource="PAGE: 5:1:1144209" waittime="2172" ownerId="1157175935" transactionname="user_transaction" lasttranstarted="2012-11-09T12:16:52.997" XDES="0x3458e63b0" lockMode="S" schedulerid="7" kpid="3912" status="suspended" spid="58" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-11-09T12:16:53.070" lastbatchcompleted="2012-11-09T12:16:53.067" clientapp=".Net SqlClient Data Provider" hostname="CWCEINAW" hostpid="4908" loginname="cwcuser" isolationlevel="read committed (2)" xactid="1157175935" currentdb="5" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
    <executionStack>
     <frame procname="adhoc" line="1" stmtstart="160" sqlhandle="0x02000000193c8a3bb37a516f7a7155b01a67b7772459f53e">
SELECT [D].*
                        FROM WP_Discrepancy as [D]
                        WHERE [D].[Level] = @Level
                        AND [D].[Status] IN (@StatusInProgress, @StatusConfirmed)
                        AND [D].[StockContainerID] = @StockContainerID     </frame>
     <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown     </frame>
    </executionStack>
    <inputbuf>
(@Level int,@StatusInProgress int,@StatusConfirmed int,@StockContainerID bigint)SELECT [D].*
                        FROM WP_Discrepancy as [D]
                        WHERE [D].[Level] = @Level
                        AND [D].[Status] IN (@StatusInProgress, @StatusConfirmed)
                        AND [D].[StockContainerID] = @StockContainerID    </inputbuf>
   </process>
  </process-list>
  <resource-list>
   <exchangeEvent id="Pipe43a6da400" WaitType="e_waitPipeGetRow" nodeId="1">
    <owner-list>
     <owner id="process33ebc8"/>
    </owner-list>
    <waiter-list>
     <waiter id="process5cd048"/>
    </waiter-list>
   </exchangeEvent>
   <pagelock fileid="1" pageid="1144344" dbid="5" objectname="WebPortal.dbo.WP_CashCenter_StockTransactionLine" id="lock326ee4180" mode="IX" associatedObjectId="72057594149601280">
    <owner-list>
     <owner id="process4e13048" mode="IX"/>
    </owner-list>
    <waiter-list>
     <waiter id="process33ebc8" mode="S" requestType="wait"/>
    </waiter-list>
   </pagelock>
   <pagelock fileid="1" pageid="1144209" dbid="5" objectname="WebPortal.dbo.WP_Discrepancy" id="lock339da6b80" mode="SIX" associatedObjectId="72057594163625984">
    <owner-list>
     <owner id="process5cd048" mode="SIX"/>
    </owner-list>
    <waiter-list>
     <waiter id="process4e13048" mode="S" requestType="wait"/>
    </waiter-list>
   </pagelock>
  </resource-list>
 </deadlock>
</deadlock-list>

ご覧のとおり、プロセスprocess4e13048は、テーブルの一部のページでIXロックを保持していますWP_CashCenter_StockTransactionLine。実行しようとしている現在のステートメントは、プロセスprocess5cd048によって保持されているSIXロックと競合する(明らかな)SELECTページ上の共有ロックが必要なため、終了できません。WP_Discrepancy

繰り返しますが、なぜ後者のプロセスがそのSIXロックを保持するのでしょうか。実行スタックによると、実行されているステートメントはSELECTtoWP_CashCenter_StockTransactionLineテーブルです。

Serializable ILを使用してトランザクションを実行している場合、同じプロセス内の前のステートメントによって取得されたロックが保持されることを期待します。しかし、そうではありません。

RC分離レベルについて何が間違っていたのか誰かに説明してもらえますか?ありがとう。

4

1 に答える 1

1

ステートメントが終了するとロックが解除されると思いました

ロックを書き込みません (X、IX、S-IX など)。書き込みロックは、トランザクションの最後に解放されるように、2 フェーズ ロックに従う必要があります。反対の意味を考えてみましょう: DELETE は、トランザクションが終了する前に削除された行の X ロックを解放し、後で並行トランザクションが同じキーを持つ新しい行を INSERT します (ロックがないため可能です)。ロールバックします。キーがその間に 2 番目のトランザクションによって取得されたため、削除した行を挿入して戻すことができず、ロールバックできません。

そのため、SELECT を実行するトランザクションは、SELECT を実行する前に書き込みロックを取得していたため、SELECT を実行するとデッドロックが発生する可能性があります。

于 2012-11-09T15:25:48.297 に答える