Kullanıcı tanımlı bir tablo türü oluşturabilir ve aynı işlemde kullanabilir miyim?


13

Aşağıdakileri yürüttüğümde (yönetim stüdyosunda GO komutları toplu olarak ayırır)

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

Bir kilitlenme hata mesajı alıyorum. Sürecim kendisiyle kilitlendi. Bu davranışı 2008, 2008 R2 ve 2012'de gördüm.

Yeni oluşturduğum türü, oluşturulduğu işlemin içinde kullanmanın bir yolu var mı?


Bunu neden bir işlemin içinde yapıyorsun? 'Geçici' bir UDT mi bekliyorsunuz?
Max Vernon

2
Bu soruyu alacağımı biliyordum. Entegrasyon testinin bir parçası. Entegrasyon testi çerçevesi her şeyi tek bir işlemde gerçekleştirir.
Michael J Swart

1
Açık bir çözüm, testi gerçekleştirmeden önce test için gerekli türleri oluşturmak olacaktır. Açıkçası, bu testi otomatikleştirmenize yardımcı olmaz.
Max Vernon

@MichaelJSwart, biraz daha ayrıntı verebilir misiniz, ne elde etmeye çalışıyorsunuz? Masa tipleri o kadar kısıtlayıcı ki, bununla gittiğini tam olarak göremiyorum.
Sebastian Meine

Yanıtlar:


15

Bu durumun en az dört kez olduğu bildirilmiştir. Bu sabit olarak kapatıldı:

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

Ama bu doğru değildi. (Ayrıca geçici çözümler bölümüne de bakın - önerdiğim geçici çözüm her zaman kabul edilebilir olmayacaktır.)

Bu tasarım tarafından kapatıldı / düzeltmeyecek:

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

Bu ikisi daha yeni ve hala aktif :

http://connect.microsoft.com/SQLServer/feedback/details/800919/ (şimdi olduğu gibi kapalı Will not Fix )

http://connect.microsoft.com/SQLServer/feedback/details/804365/ (artık Tasarım gereği kapalı )

Microsoft başka türlü ikna oluncaya kadar, bir geçici çözüm bulmak zorunda kalacaksınız - yalnızca testinizi çalıştırmadan önce tüm türlerin dağıtılmasını sağlayın veya birden çok sınamaya bölün.

Umachandar'ın en erken maddede düzeltilmesi ile ne anlama geldiği konusunda kişilerimden onay almaya çalışacağım, çünkü daha sonraki ifadelerle çelişiyor.

GÜNCELLEME # 1 (umarım tam 2)

Orijinal hata (sabit olarak kapatıldı) diğer türler içeriyordu, ancak tür değil TABLE. Tabii ki tablo türleri ve TVP'leri olmayan SQL Server 2005'e karşı rapor edildi. UC, tablo dışı takma türlerle ilgili hatanın dahili işlemleri nasıl ele aldıklarına göre düzeltildiğini bildirdi, ancak daha sonra tablo türleriyle tanıtılan benzer bir senaryoyu kapsamıyordu. Hala orijinal hata hiç sabit olarak kapatılmış olup olmadığını onay bekliyor; Dördünün de tasarımdaki gibi kapatılmasını önerdim. Bunun nedeni, kısmen çalışmasını nasıl beklediğim ve kısmen de farklı bir şekilde çalışmak için "sabitlemenin" son derece karmaşık, geriye dönük uyumluluğu bozabileceği ve çok sınırlı sayıda kullanım durumu. Size veya kullanım durumunuza karşı hiçbir şey yok, ancak test senaryoları dışında ben

GÜNCELLEME # 2

Bu konuda blog yazdım:

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


1

Bunu yeniden üretebildim. Kilitlenme grafiği oldukça meraklı:

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

Bana bir hata gibi görünüyor ve bunun için bir bağlantı öğesi açmanızı tavsiye ederim.


Anında sorununuzu çözmek için kullanabilirsiniz tSQLt.NewConnection(varsayalım tSQLt kullandığınızı)

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

Hala bir masa tipi yaratma ihtiyacının nereden geldiğini anlamıyorum ve testinizi aşırı karmaşıklaştırdığınızı varsayıyorum. Tartışmak isterseniz bana bir e-posta gönderin.


2
Yardımın için teşekkürler Sebastian. Ne yazık ki, tSQLt kullanmıyorum. Anında bir tür yaratma ihtiyacının nereden geldiğini anlamıyorsunuz çünkü açıklamamıştım. Bir şeyleri çok karmaşık yapmıyorum, ama bunu gösterme gereğini hissetmiyorum.
Michael J Swart

Peki, tSQLt.NewConnection'ın nasıl uygulandığına ilişkin tSQLt kaynak koduna bakın. Oldukça basittir ve çerçevenizde de çalışmalıdır.
Sebastian Meine

1
Türü oluşturma ve daha sonra aynı işlemde kullanma girişimleri kilitlenmeyle sonuçlanır (Aaron'un son bağlantısına bağlanan hata raporuma bakın); bu geçici çözüm çalışmaz (giriş deyimini çalıştırmadan önce açık bir işlem yapmak gibi aptalca bir şey yapmadığı varsayılarak).
Jon Seigel

-1

Birisi farklı bilmediği sürece, bunu tek bir işlemde yapmanın bir yolu olduğunu sanmıyorum. Bunun bir hata olduğunu düşünmüyorum.

İlk olarak, türü oluştururken bir şema değiştirme kilidi (Sch-M) almanız gerekir. İşlemi yapmadığınız için kilit açık kalır. Sonra aynı işlemde bu tür için bir değişken bildirmeye çalışın. Bu bir Şema Kararlılığı kilidi (Sch-S) almaya çalışır. Bu iki tür aynı nesne üzerinde aynı anda uyumsuzdur. Aynı işlemde olduklarından SQL, işlem açıkken Sch-S'ye asla izin verilemediğinden buna bir kilitlenme olarak davranır.

Her toplu işi birer birer çalıştırın ve değişkeni bildirmeye çalıştığınızda sys.dm_tran_locks'a karşı seçim yapın. Aynı işlemi bir Sch-M tutarak ve aynı nesne üzerinde bir Sch-S beklerken göreceksiniz.


3
Türler uyumsuz, ama aynı sürecin kendisini beklemek zorunda kalmayacağını düşündüm. Örneğin, bir tabloya bir sütun ekleyebilir ve aynı işlemde kullanabilirsiniz.
Michael J Swart

3
Kilit yöneticisi, işlemin kaynak üzerinde zaten (gerçekten daha güçlü) bir kilidi tuttuğunu ve işlemin beklemek zorunda olmadığını anlamalıdır. Sonuçta ilk önce bir satırı güncelleyebilir ve daha sonra aynı durumda tekrar okuyabilirsiniz.
Sebastian Meine
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.