ฉันสามารถสร้างประเภทตารางที่ผู้ใช้กำหนดและใช้ในธุรกรรมเดียวกันได้หรือไม่?


13

เมื่อฉันดำเนินการต่อไปนี้ (ในสตูดิโอการจัดการ 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

มีวิธีใช้ประเภทที่สร้างขึ้นใหม่ของฉันภายในธุรกรรมเดียวกันกับที่สร้างขึ้นหรือไม่


ทำไมคุณถึงทำสิ่งนี้ในการทำธุรกรรม? คุณหวังว่าจะเป็น 'ชั่วคราว' UDT หรือไม่?
Max Vernon

2
ฉันรู้ว่าฉันจะได้รับคำถามนี้ มันเป็นส่วนหนึ่งของการทดสอบการรวม เฟรมเวิร์กการทดสอบการรวมทำทุกอย่างในธุรกรรมเดียว
Michael J Swart

1
วิธีแก้ปัญหาที่ชัดเจนคือการสร้างประเภทที่จำเป็นสำหรับการทดสอบก่อนดำเนินการทดสอบ เห็นได้ชัดว่านั่นไม่ได้ช่วยให้คุณทำการทดสอบอัตโนมัติ
Max Vernon

@MichaelJSwart คุณช่วยอธิบายเพิ่มเติมอีกหน่อยได้ไหมว่าคุณพยายามทำอะไรให้สำเร็จ ชนิดของตารางมีข้อ จำกัด มากจนฉันไม่สามารถเห็นได้ว่าคุณกำลังทำอะไรอยู่
เซบาสเตียนมีน

1
FYI ฉันเขียนบล็อกเกี่ยวกับsqlperformance.com/2013/11/t-sql-queries/single-tx-deadlock
Aaron Bertrand

คำตอบ:


15

เรื่องนี้มีการรายงานไม่น้อยกว่าสี่ครั้ง อันนี้ถูกปิดเป็นคงที่:

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

แต่นั่นไม่เป็นความจริง (ดูที่ส่วนการแก้ไขปัญหาด้วย - วิธีแก้ปัญหาที่ฉันแนะนำไม่ได้เป็นที่ยอมรับเสมอไป)

อันนี้ถูกปิดตามการออกแบบ / จะไม่แก้ไข:

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

สองสิ่งนี้ใหม่กว่าและยังคงใช้งานอยู่ :

http://connect.microsoft.com/SQLServer/feedback/details/800919/ (ตอนนี้ปิดเนื่องจากไม่สามารถแก้ไขได้ )

http://connect.microsoft.com/SQLServer/feedback/details/804365/ (ตอนนี้ปิดตามการออกแบบ )

จนกว่า Microsoft จะมั่นใจได้เป็นอย่างอื่นคุณจะต้องหาวิธีแก้ปัญหา - เพียงแค่มีการติดตั้งทุกประเภทก่อนที่จะทำการทดสอบหรือแบ่งเป็นการทดสอบหลาย ๆ แบบ

ฉันจะพยายามรับการยืนยันจากผู้ติดต่อของฉันเกี่ยวกับความหมายของ Umachandar โดยการแก้ไขในรายการแรกสุดเพราะเห็นได้ชัดว่าขัดแย้งกับข้อความในภายหลัง

อัปเดต # 1 (จากหวังว่าอย่างแน่นอน 2)

ข้อผิดพลาดดั้งเดิม (ที่ถูกปิดเป็นคงที่) เกี่ยวข้องกับประเภทนามแฝง แต่ไม่ใช่ประเภท TABLE. มีการรายงานกับ SQL Server 2005 ซึ่งเห็นได้ชัดว่าไม่มีประเภทตารางและ TVPs ดูเหมือนว่า UC รายงานว่าข้อผิดพลาดที่มีประเภทนามแฝงที่ไม่ใช่ตารางได้รับการแก้ไขตามวิธีที่พวกเขาจัดการธุรกรรมภายใน แต่ก็ไม่ได้ครอบคลุมสถานการณ์ที่คล้ายกันในภายหลังที่นำมาใช้กับประเภทตาราง ฉันยังคงรอการยืนยันว่าข้อผิดพลาดเดิมนั้นควรถูกปิดอย่างถาวรหรือไม่ ฉันแนะนำว่าทั้งสี่ถูกปิดโดยการออกแบบ ส่วนหนึ่งเป็นเพราะมันเป็นวิธีที่ฉันคาดหวังว่ามันจะทำงานและส่วนหนึ่งเป็นเพราะฉันได้รับความรู้สึกจาก UC ว่า "การแก้ไข" เพื่อให้ทำงานในวิธีที่แตกต่างมีความซับซ้อนมากสามารถทำลายความเข้ากันได้แบบย้อนหลัง จำนวนกรณีการใช้งานที่ จำกัด มาก ไม่มีอะไรกับคุณหรือกรณีการใช้งานของคุณ แต่อยู่นอกสถานการณ์การทดสอบฉัน

อัปเดต # 2

ฉัน blogged เกี่ยวกับปัญหานี้:

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


1

ฉันสามารถทำซ้ำสิ่งนี้ กราฟการหยุดชะงักค่อนข้างน่าสงสัย:

<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

ฉันยังไม่เข้าใจว่าจำเป็นต้องสร้างประเภทตารางแบบทันทีหรือเปล่าและฉันคิดว่าคุณมีความยุ่งยากในการทดสอบมากเกินไป ส่งอีเมลถึงฉันถ้าคุณต้องการที่จะหารือ


2
ขอบคุณสำหรับความช่วยเหลือของคุณเซบาสเตียน น่าเสียดายที่ฉันไม่ได้ใช้ tSQLt คุณไม่เข้าใจว่าต้องสร้างประเภทใดขึ้นมาทันทีเพราะฉันไม่ได้อธิบาย ฉันไม่ได้ซับซ้อนเกินไป แต่ฉันไม่รู้สึกว่าจำเป็นต้องแสดงมัน
Michael J Swart

ดูที่ซอร์สโค้ด tSQLt ว่ามีการใช้งาน tSQLt.NewConnection อย่างไร มันค่อนข้างตรงไปตรงมาและควรทำงานในกรอบของคุณด้วย
เซบาสเตียนมีน

1
ความพยายามใด ๆ ในการสร้างประเภทและจากนั้นใช้มันในการทำธุรกรรมเดียวกันผลในการหยุดชะงัก (ดูรายงานข้อผิดพลาดของฉันเชื่อมโยงในโพสต์โพสต์ - ลิงค์ล่าสุดของแอรอน); วิธีแก้ปัญหานี้จะไม่ทำงาน (เช่นกันสมมติว่ามันไม่ได้ทำอะไรที่โง่เหมือนการคอมมิชชันทรานแซคชันก่อนที่จะประมวลผลคำสั่งอินพุต)
Jon Seigel

-1

หากไม่มีใครรู้ที่แตกต่างฉันไม่คิดว่าจะมีวิธีการทำเช่นนี้ในการทำธุรกรรมเดียว ฉันไม่คิดว่านี่เป็นข้อผิดพลาด

ก่อนอื่นคุณต้องทำการล็อคการปรับเปลี่ยน schema (Sch-M) เมื่อคุณสร้างประเภท เนื่องจากคุณไม่ได้ทำธุรกรรมล็อคยังคงเปิดอยู่ จากนั้นคุณพยายามประกาศตัวแปรประเภทนั้นในธุรกรรมเดียวกัน สิ่งนี้พยายามที่จะล็อค Schema Stability (Sch-S) ทั้งสองประเภทนั้นไม่สามารถใช้งานร่วมกันบนวัตถุเดียวกันได้พร้อมกัน เนื่องจากอยู่ในธุรกรรมเดียวกัน SQL จึงถือว่าเป็นการหยุดชะงักเนื่องจาก Sch-S ไม่สามารถได้รับในขณะที่ธุรกรรมเปิดอยู่

รันแต่ละชุดทีละชุดและเลือกเทียบกับ sys.dm_tran_locks ทันทีที่คุณพยายามประกาศตัวแปร คุณจะเห็นกระบวนการเดียวกันถือ Sch-M และรอ Sch-S บนวัตถุเดียวกัน


3
ประเภทไม่เข้ากัน แต่ฉันคิดว่ากระบวนการเดียวกันไม่ต้องรอตัวเอง ตัวอย่างเช่นฉันสามารถเพิ่มคอลัมน์ลงในตารางและใช้ในธุรกรรมเดียวกันได้
Michael J Swart

3
ตัวจัดการการล็อกควรเข้าใจว่ากระบวนการกำลังทำการล็อค (แรงขึ้นจริง) บนทรัพยากรที่มีอยู่แล้วและกระบวนการไม่ควรรอ คุณสามารถอัปเดตแถวแรกแล้วอ่านกลับในสถานการณ์เดียวกัน
เซบาสเตียนมีน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.