Bisakah saya membuat tipe tabel yang ditentukan pengguna dan menggunakannya dalam transaksi yang sama?

13

Ketika saya menjalankan yang berikut (di studio manajemen, GO akan memisahkan perintah menjadi beberapa)

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

Saya mendapatkan pesan kesalahan jalan buntu. Proses saya menemui jalan buntu. Saya telah melihat perilaku ini pada 2008, 2008R2 dan 2012.

Apakah ada cara untuk menggunakan tipe yang baru saya buat dalam transaksi yang sama dengan yang dibuat?

Michael J Swart
sumber
Mengapa Anda melakukan ini di dalam transaksi? Apakah Anda mengharapkan UDT 'sementara'?
Max Vernon
2
Saya tahu saya akan mendapatkan pertanyaan ini. Itu bagian dari tes integrasi. Kerangka kerja pengujian integrasi melakukan semuanya dalam satu transaksi.
Michael J Swart
1
Solusi yang jelas adalah membuat jenis yang diperlukan untuk pengujian sebelum melaksanakan tes. Jelas, itu tidak membantu Anda mengotomatisasi pengujian.
Max Vernon
@MichaelJSwart, bisakah Anda menguraikan lebih sedikit, apa yang ingin Anda capai? Jenis tabel sangat terbatas, sehingga saya tidak bisa melihat apakah Anda akan melakukannya.
Sebastian Meine
1
FYI Saya membuat blog tentang sqlperformance.com/2013/11/t-sql-queries/single-tx-deadlock
Aaron Bertrand

Jawaban:

15

Ini telah dilaporkan tidak kurang dari empat kali. Yang ini ditutup sebagai sudah diperbaiki:

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

Tapi itu tidak benar. (Lihat juga bagian pemecahan masalah - solusi yang saya sarankan tidak selalu dapat diterima.)

Yang ini ditutup karena desain / tidak akan diperbaiki:

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

Keduanya lebih baru dan masih aktif :

http://connect.microsoft.com/SQLServer/feedback/details/800919/ (sekarang ditutup karena tidak akan diperbaiki )

http://connect.microsoft.com/SQLServer/feedback/details/804365/ (sekarang ditutup dengan Desain )

Sampai Microsoft dapat diyakinkan sebaliknya, Anda harus menemukan solusi - cukup gunakan semua jenis sebelum menjalankan tes Anda, atau pecahkan menjadi beberapa tes.

Saya akan mencoba untuk mendapatkan konfirmasi dari kontak saya tentang apa yang dimaksud Umachandar dengan diperbaiki di item paling awal, karena jelas itu bertentangan dengan pernyataan kemudian.

UPDATE # 1 (dari, semoga, tepat 2)

Bug asli (yang ditutup sebagai diperbaiki) melibatkan tipe alias, tetapi bukan tipe TABLE. Dilaporkan terhadap SQL Server 2005, yang jelas tidak memiliki tipe tabel dan TVP. Tampaknya UC melaporkan bahwa bug dengan tipe alias non-tabel diperbaiki berdasarkan bagaimana mereka menangani transaksi internal, tetapi tidak mencakup skenario serupa yang kemudian diperkenalkan dengan tipe tabel. Saya masih menunggu konfirmasi apakah bug asli itu seharusnya pernah ditutup sebagai diperbaiki; Saya telah menyarankan agar keempat ditutup sebagai oleh desain. Ini sebagian karena ini adalah jenis bagaimana saya berharap itu berfungsi, dan sebagian karena saya mendapatkan pengertian dari UC bahwa "memperbaikinya" bekerja dengan cara yang berbeda sangat kompleks, dapat merusak kompatibilitas ke belakang, dan akan membantu dalam jumlah kasus penggunaan yang sangat terbatas. Tidak ada yang menentang Anda atau kasus penggunaan Anda, tetapi di luar skenario pengujian saya

PEMBARUAN # 2

Saya sudah membuat blog tentang masalah ini:

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

Aaron Bertrand
sumber
1

Saya bisa mereproduksi ini. Grafik deadlock cukup penasaran:

<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>

Bagiku itu terlihat seperti bug dan saya sarankan Anda membuka item connect untuk itu.


Untuk menyiasati masalah langsung Anda, Anda dapat menggunakan tSQLt.NewConnection(saya berasumsi Anda menggunakan 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

Saya masih tidak mengerti dari mana kebutuhan untuk membuat jenis tabel dengan cepat berasal dan saya menganggap Anda terlalu rumit ujian Anda. Kirim saya email jika Anda ingin berdiskusi.

Sebastian Meine
sumber
2
Terima kasih atas bantuan Anda, Sebastian. Sayangnya, saya tidak menggunakan tSQLt. Anda tidak mengerti dari mana kebutuhan untuk membuat jenis dengan cepat berasal dari karena saya tidak menjelaskannya. Saya tidak terlalu rumit, tapi saya tidak merasa perlu menunjukkannya.
Michael J Swart
Nah, lihat kode sumber tSQLt tentang bagaimana tSQLt.NewConnection diimplementasikan. Ini cukup mudah dan harus bekerja dalam kerangka kerja Anda juga.
Sebastian Meine
1
Setiap upaya untuk membuat jenis dan kemudian menggunakannya dalam transaksi yang sama menghasilkan jalan buntu (lihat laporan bug saya, ditautkan pada tautan pasca-terakhir Harun); solusi ini tidak akan berhasil (well, dengan asumsi itu tidak melakukan sesuatu yang bodoh seperti melakukan transaksi terbuka sebelum mengeksekusi pernyataan input).
Jon Seigel
-1

Kecuali ada orang yang tahu perbedaannya, saya tidak berpikir ada cara untuk melakukan ini dalam satu transaksi. Saya rasa ini bukan bug.

Pertama, Anda perlu mengambil kunci modifikasi skema (Sch-M) saat Anda membuat tipe. Karena Anda tidak melakukan transaksi, kunci tetap terbuka. Kemudian Anda mencoba mendeklarasikan variabel ke jenis itu dalam transaksi yang sama. Ini mencoba untuk mengambil kunci Stabilitas Skema (Sch-S). Kedua jenis itu tidak kompatibel secara bersamaan pada objek yang sama. Karena mereka dalam transaksi yang sama, SQL memperlakukannya sebagai jalan buntu karena Sch-S tidak pernah dapat diberikan saat transaksi terbuka.

Jalankan setiap batch satu per satu, dan pilih terhadap sys.dm_tran_locks segera setelah Anda mencoba mendeklarasikan variabel. Anda akan melihat proses yang sama memegang Sch-M dan menunggu Sch-S pada objek yang sama.

dmmaxwell
sumber
3
Jenisnya tidak kompatibel, tetapi saya berpikir bahwa proses yang sama tidak harus menunggu sendiri. Misalnya, saya bisa menambahkan kolom ke tabel dan kemudian menggunakannya dalam transaksi yang sama.
Michael J Swart
3
Manajer kunci harus mengetahui bahwa proses sudah memegang kunci (sebenarnya lebih kuat) pada sumber daya dan proses tidak harus menunggu. Anda dapat memperbarui dulu satu baris dan kemudian membacanya kembali dalam situasi yang sama.
Sebastian Meine