Tôi có thể tạo loại bảng do người dùng xác định và sử dụng nó trong cùng một giao dịch không?


13

Khi tôi thực hiện các thao tác sau (trong studio quản lý, GO sẽ tách các lệnh thành các đợt)

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

Tôi nhận được một thông báo lỗi bế tắc. Quá trình của tôi đã bế tắc với chính nó. Tôi đã thấy hành vi này trong năm 2008, 2008R2 và 2012.

Có cách nào để sử dụng loại vừa tạo của tôi trong cùng một giao dịch mà nó đã được tạo không?


Tại sao bạn làm điều này trong một giao dịch? Bạn có hy vọng cho một UDT 'tạm thời' không?
Max Vernon

2
Tôi biết tôi sẽ nhận được câu hỏi này. Đó là một phần của bài kiểm tra tích hợp. Khung kiểm tra tích hợp thực hiện mọi thứ trong một giao dịch.
Michael J Swart

1
Một cách giải quyết rõ ràng sẽ là tạo ra các loại cần thiết cho thử nghiệm trước khi thực hiện thử nghiệm. Rõ ràng, điều đó không giúp bạn tự động hóa việc kiểm tra, tuy nhiên.
Max Vernon

@MichaelJSwart, bạn có thể nói rõ hơn một chút, những gì bạn đang cố gắng để đạt được? Các loại bảng rất hạn chế, mà tôi không thể thấy được là bạn đang làm gì với điều này.
Sebastian Meine

Câu trả lời:


15

Điều này đã được báo cáo không dưới bốn lần. Cái này đã được đóng lại như là cố định:

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

Nhưng điều đó không đúng. (Cũng xem phần giải pháp thay thế - cách giải quyết mà tôi đề xuất không phải lúc nào cũng được chấp nhận.)

Cái này đã bị đóng do thiết kế / sẽ không sửa:

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

Hai cái này mới hơn và vẫn còn hoạt động :

http://connect.microsoft.com/QueryServer/feedback/details/800919/ (hiện đã đóng cửa khi không sửa )

http://connect.microsoft.com/SQLServer/feedback/details/804365/ (hiện đã đóng dưới dạng Thiết kế )

Cho đến khi Microsoft có thể bị thuyết phục theo cách khác, bạn sẽ phải tìm một cách giải quyết - chỉ cần có tất cả các loại được triển khai trước khi chạy thử nghiệm của bạn hoặc chia nó thành nhiều thử nghiệm.

Tôi sẽ cố gắng để có được xác nhận từ các liên hệ của tôi về ý nghĩa của Umachandar trong mục sớm nhất, bởi vì rõ ràng điều đó mâu thuẫn với các tuyên bố sau.

CẬP NHẬT # 1 (của, hy vọng, chính xác là 2)

Lỗi ban đầu (đã được đóng dưới dạng cố định) liên quan đến các loại bí danh, nhưng không phải là loại TABLE. Nó đã được báo cáo chống lại SQL Server 2005, rõ ràng là không có loại bảng và TVP. Có vẻ như UC đã báo cáo rằng lỗi với các loại bí danh không phải bảng đã được sửa dựa trên cách họ xử lý các giao dịch nội bộ, nhưng nó không bao gồm một kịch bản tương tự sau đó được giới thiệu với các loại bảng. Tôi vẫn đang chờ xác nhận xem lỗi ban đầu đó có nên được đóng lại như đã sửa hay không; Tôi đã đề nghị rằng tất cả bốn được đóng cửa theo thiết kế. Điều này một phần vì đó là cách tôi mong đợi nó hoạt động, và một phần vì tôi hiểu rằng UC "sửa" nó hoạt động theo một cách khác là cực kỳ phức tạp, có thể phá vỡ khả năng tương thích ngược và sẽ hữu ích trong số lượng sử dụng rất hạn chế. Không có gì chống lại bạn hoặc trường hợp sử dụng của bạn, nhưng ngoài các kịch bản thử nghiệm tôi '

CẬP NHẬT # 2

Tôi đã viết về vấn đề này:

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


1

Tôi đã có thể tái tạo điều này. Biểu đồ bế tắc khá tò mò:

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

Nó trông giống như một lỗi và tôi khuyên bạn nên mở một mục kết nối cho nó.


Để giải quyết vấn đề tức thời của bạn, bạn có thể sử dụng tSQLt.NewConnection(Tôi giả sử bạn đang sử dụng tQueryt)

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

Tôi vẫn không hiểu nhu cầu tạo ra một loại bảng đang đến từ đâu và tôi cho rằng bạn đang làm quá phức tạp bài kiểm tra của mình. Gửi cho tôi một email nếu bạn muốn thảo luận.


2
Cảm ơn sự giúp đỡ của bạn Sebastian. Thật không may, tôi không sử dụng tQueryt. Bạn không hiểu nhu cầu tạo ra một loại trên bay đến từ đâu vì tôi đã không giải thích nó. Tôi không quá phức tạp, nhưng tôi không cảm thấy cần phải chứng minh điều đó.
Michael J Swart

Chà, hãy nhìn vào mã nguồn của tQueryt về cách thức tQueryt.NewConnection được triển khai. Nó khá thẳng về phía trước và cũng nên hoạt động trong khuôn khổ của bạn.
Sebastian Meine

1
Bất kỳ nỗ lực nào để tạo loại và sau đó sử dụng nó trong cùng một giao dịch đều dẫn đến bế tắc (xem báo cáo lỗi của tôi, được liên kết trong bài đăng cuối cùng của Aaron); cách giải quyết này sẽ không hoạt động (tốt, giả sử nó không làm điều gì ngớ ngẩn như thực hiện giao dịch mở trước khi thực hiện câu lệnh đầu vào).
Jon Seigel

-1

Trừ khi ai đó biết khác nhau, tôi không nghĩ có cách nào để thực hiện điều này trong một giao dịch. Tôi không nghĩ rằng đây là một lỗi.

Trước tiên, bạn cần thực hiện khóa sửa đổi lược đồ (Sch-M) khi bạn tạo kiểu. Vì bạn không thực hiện giao dịch, khóa vẫn mở. Sau đó, bạn cố gắng khai báo một biến cho loại đó trong cùng một giao dịch. Điều này cố gắng thực hiện khóa Ổn định Schema (Sch-S). Hai loại này không tương thích đồng thời trên cùng một đối tượng. Vì chúng nằm trong cùng một giao dịch, SQL coi nó như một sự bế tắc vì Sch-S không bao giờ có thể được cấp trong khi giao dịch được mở.

Chạy từng đợt một tại một thời điểm và chọn chống lại sys.dm_tran_locks ngay khi bạn cố gắng khai báo biến. Bạn sẽ thấy quy trình tương tự giữ Sch-M và chờ Sch-S trên cùng một đối tượng.


3
Các loại không tương thích, nhưng tôi nghĩ rằng quá trình tương tự sẽ không phải chờ đợi. Ví dụ: tôi có thể thêm một cột vào bảng và sau đó sử dụng nó trong cùng một giao dịch.
Michael J Swart

3
Người quản lý khóa nên tìm ra rằng quy trình đang giữ khóa (thực sự mạnh hơn) trên tài nguyên đã có và quy trình không phải chờ. Sau tất cả, bạn có thể cập nhật một hàng đầu tiên và sau đó đọc lại trong tình huống tương tự.
Sebastian Meine
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.