都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

デッドロックについて説明してみる - その 4 ( さらに、デッドロックの内容をみてみる ) -

 世間はすっかりハロウィーンムード。用事を済ませた後、立ち寄ったドトールのコーヒーもハロウィーン仕様でした。
 f:id:koogucc11:20161029144449j:plain

 デッドロックの続きです。次はトレースフラグ 1204 の説明をします。下記の二つの記事から、トレースフラグ 1204 を設定し、デッドロックを発生させてみましょう。
ryuchan.hatenablog.com
ryuchan.hatenablog.com

 前回同様デッドロックが発生しました。
f:id:koogucc11:20161024131058p:plain

 それでは、ERROR ログの内容を参照してみましょう。デッドロック対象となったプロセスは、46,47行目に出力されています。SPID:53 で発行したクエリがデッドロック対象となったことがわかります。どのリソースでロックが発生しているかは、6,27行目に出力されています。

  1. Deadlock encountered .... Printing deadlock information
  2. Wait-for graph
  3. Node:1
  4. KEY: 10:72057594047365120 (61a06abd401c) CleanCnt:2 Mode:X Flags: 0x1
  5. Grant List 3:
  6. Owner:0x0000026DD2E5F280 Mode: X Flg:0x40 Ref:0 Life:02000000 SPID:51 ECID:0 XactLockInfo: 0x0000026DEBAA7250
  7. SPID: 51 ECID: 0 Statement Type: UPDATE Line #: 17
  8. Input Buf: Language Event: DECLARE @Error_Message NVARCHAR(MAX);
  9. DECLARE @Error_Severity INT;
  10. DECLARE @Error_State INT;
  11. WHILE 0 = 0
  12. BEGIN
  13. BEGIN TRY
  14. BEGIN TRAN
  15. -- ProductID = 2 のデータを更新する。
  16. UPDATE
  17. Production.Product
  18. SET
  19. Requested by:
  20. ResType:LockOwner Stype:\'OR\'Xdes:0x0000026DF7554878 Mode: U SPID:53 BatchID:0 ECID:0 TaskProxy:(0x0000026DCF5A2880) Value:0xd2e5e280 Cost:(0/144)
  21. Node:2
  22. KEY: 10:72057594047365120 (8194443284a0) CleanCnt:2 Mode:X Flags: 0x1
  23. Grant List 3:
  24. Owner:0x0000026DD2E6F680 Mode: X Flg:0x40 Ref:0 Life:02000000 SPID:53 ECID:0 XactLockInfo: 0x0000026DF75548B0
  25. SPID: 53 ECID: 0 Statement Type: UPDATE Line #: 17
  26. Input Buf: Language Event: DECLARE @Error_Message NVARCHAR(MAX);
  27. DECLARE @Error_Severity INT;
  28. DECLARE @Error_State INT;
  29. WHILE 0 = 0
  30. BEGIN
  31. BEGIN TRY
  32. BEGIN TRAN
  33. -- ProductID = 1 のデータを更新する。
  34. UPDATE
  35. Production.Product
  36. SET
  37. Requested by:
  38. ResType:LockOwner Stype:\'OR\'Xdes:0x0000026DEBAA7218 Mode: U SPID:51 BatchID:0 ECID:0 TaskProxy:(0x0000026D92B5C880) Value:0xd2e6eb80 Cost:(0/144)
  39. Victim Resource Owner:
  40. ResType:LockOwner Stype:\'OR\'Xdes:0x0000026DF7554878 Mode: U SPID:53 BatchID:0 ECID:0 TaskProxy:(0x0000026DCF5A2880) Value:0xd2e5e280 Cost:(0/144)

 下記のように KEY 範囲でのロックが出力されていますが、イマイチどのように特定していいのかわかりません。MSDN には下記のように記載されています。hobt_id を用いて sys.partitions (Transact-SQL) を参照することで対象のテーブル、インデックスまで特定することは可能ですが、どのデータで発生したかを特定する方法はありません。

KEY。ロックが保持または要求されているインデックス内のキー範囲を識別します。KEY は KEY: db_id:hobt_id (index key hash value) で表されます。たとえば、KEY: 6:72057594057457664 (350007a4d329) のようにします。

 ここで使用するのが、Undocumented Virtual Column です。下記のクエリを SQL Server Management Studio で実行してみましょう。

SELECT 
    %%lockres%%, 
    p.*
FROM 
    Production.Product p
WHERE 
    %%lockres%% IN ('(8194443284a0)','(61a06abd401c)')

 index key hash value を使用して対象となった行を特定することができました。
f:id:koogucc11:20161029151205p:plain

 まだまだ、undocumented あるんですね。深いです。

 ハロウィーンで仮装とかしたことないなぁ。

THE HALLOWEEN collection ふわもこ パンプキン

THE HALLOWEEN collection ふわもこ パンプキン