web-dev-qa-db-ja.com

ユーザー定義のテーブルタイプを作成して、同じトランザクションで使用できますか?

次を実行すると(Management Studioでは、GOはコマンドをバッチに分割します)

use tempdb

begin tran
go

CREATE TYPE dbo.IntIntSet AS TABLE(
    Value0 Int NOT NULL,
    Value1 Int NOT NULL
)
go

declare @myPK dbo.IntIntSet;
go

rollback

デッドロックエラーメッセージが表示されます。私のプロセスはそれ自体で行き詰まっています。この動作は2008、2008R2、2012で見られました。

新しく作成したタイプを、それが作成されたのと同じトランザクション内で使用する方法はありますか?

13
Michael J Swart

これは4回以上報告されています。これは修正されてクローズされました:

http://connect.Microsoft.com/SQLServer/feedback/details/365876/

しかし、それは真実ではありませんでした。 (回避策のセクションも参照してください-私が提案した回避策は常に受け入れられるとは限りません。)

これは仕様により閉じられました/修正されません:

http://connect.Microsoft.com/SQLServer/feedback/details/581193/

これらの2つは新しいです そしてまだアクティブ

http://connect.Microsoft.com/SQLServer/feedback/details/800919/として閉じられたため、修正されません

http://connect.Microsoft.com/SQLServer/feedback/details/804365/ (現在By Designとして閉じられています)

Microsoftが別の方法で納得できるまで、回避策を見つける必要があります。テストを実行する前にすべてのタイプを展開するか、複数のテストに分割するだけです。

連絡先から、最初のアイテムで修正されたUmachandarの意味を確認しようとします。これは明らかに後のステートメントと競合するためです。

UPDATE#1(うまくいけば、ちょうど2)

元のバグ(修正されてクローズされた)にはエイリアスタイプが含まれていましたが、タイプTABLEではありませんでした。 SQL Server 2005に対して報告されましたが、テーブルタイプとTVPはありませんでした。 UCは、非テーブルエイリアスタイプのバグが内部トランザクションの処理方法に基づいて修正されたと報告しているようですが、後でテーブルタイプで導入された同様のシナリオはカバーされませんでした。その元のバグが修正されてクローズされるべきかどうかの確認を私はまだ待っています。設計上、4つすべてを閉じることをお勧めします。これは、一部は私がそれが機能することを期待していたためであり、一部は、UCから別の方法で機能するように「修正」することは非常に複雑であり、下位互換性を損なう可能性があり、非常に限られた数のユースケース。あなたやあなたのユースケースに反することはありませんが、テストシナリオ以外では、これが実際に機能することに多くの価値があるとは思いません。

更新#2

私はこの問題についてブログに書いています:

http://www.sqlperformance.com/2013/11/t-sql-queries/single-tx-deadlock

15
Aaron Bertrand

これを再現できました。デッドロックグラフはかなり興味深いものです。

<deadlock-list>
  <deadlock victim="process47f948">
    <process-list>
      <process id="process47f948" taskpriority="0" logused="0" waitresource="METADATA: database_id = 2 USER_TYPE(user_type_id = 257)" waittime="3607" ownerId="14873" transactionname="@myPK" lasttranstarted="2013-11-06T13:23:12.177" XDES="0x80f6d950" lockMode="Sch-S" schedulerid="1" kpid="2672" status="suspended" spid="54" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2013-11-06T13:23:12.167" lastbatchcompleted="2013-11-06T13:23:12.163" clientapp="Microsoft SQL Server Management Studio - Query" hostname="xxxxx" hostpid="5276" loginname="xxxxx\xxxxx" isolationlevel="read committed (2)" xactid="14867" currentdb="2" lockTimeout="4294967295" clientoption1="671090784" clientoption2="390200">
        <executionStack>
          <frame procname="adhoc" line="2" sqlhandle="0x010002002d9fe3155066b380000000000000000000000000">
declare @myPK dbo.IntIntSet;     </frame>
        </executionStack>
        <inputbuf>

declare @myPK dbo.IntIntSet;
    </inputbuf>
      </process>
    </process-list>
    <resource-list>
      <metadatalock subresource="USER_TYPE" classid="user_type_id = 257" dbid="2" id="lock8009cc00" mode="Sch-M">
        <owner-list>
          <owner id="process47f948" mode="Sch-M" />
        </owner-list>
        <waiter-list>
          <waiter id="process47f948" mode="Sch-S" requestType="wait" />
        </waiter-list>
      </metadatalock>
    </resource-list>
  </deadlock>
</deadlock-list>

バグのように見えますが、そのための接続アイテムを開くことをお勧めします。


差し迫った問題を回避するには、tSQLt.NewConnection(tSQLtを使用していると思います)

use tempdb

begin tran
go
EXEC tSQLt.NewConnection '
CREATE TYPE dbo.IntIntSet AS TABLE(
    Value0 Int NOT NULL,
    Value1 Int NOT NULL
)
';
go

declare @myPK dbo.IntIntSet;
go

rollback

オンザフライでテーブルタイプを作成する必要性がどこから来ているのかまだ理解できません。テストが非常に複雑になっていると思います。話し合いをしたい場合はメールを送ってください。

1
Sebastian Meine