사용자 정의 테이블 유형을 작성하여 동일한 트랜잭션에서 사용할 수 있습니까?


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, 당신이 달성하려는 것을 조금 더 자세히 설명해 주시겠습니까? 테이블 유형은 너무 제한적 이므로이 작업을하고 있는지 알 수 없습니다.
Sebastian Meine

답변:


15

이것은 4 번 이상보고되었습니다. 이것은 고정 된 것으로 닫혔습니다.

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. 테이블 유형과 TVP가없는 SQL Server 2005에 대해보고되었습니다. UC는 테이블이 아닌 별칭 유형의 버그가 내부 트랜잭션을 처리하는 방식에 따라 수정되었다고보고했지만 나중에 테이블 유형으로 도입 된 유사한 시나리오는 다루지 않았습니다. 나는 원래 버그가 수정 된대로 닫혀 져야하는지에 대한 확인을 여전히 기다리고있다. 나는 디자인에 따라 4 개 모두를 닫을 것을 제안했다. 이것은 부분적으로 그것이 내가 어떻게 작동하는지 예상했기 때문이며, 부분적으로 UC에서 다른 방식으로 작동하도록 "고정"하는 것이 극히 복잡하고 역 호환성을 깨뜨릴 수 있고 매우 제한된 수의 사용 사례. 당신이나 당신의 유스 케이스에 반대하는 것은 없지만 테스트 시나리오 이외의 나는

업데이트 # 2

이 문제에 대해 블로그에 올렸습니다.

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.NewConnection이 어떻게 구현되는지 tSQLt 소스 코드를 살펴보십시오. 상당히 간단하며 프레임 워크에서도 작동해야합니다.
Sebastian Meine

1
형식을 만든 다음 동일한 트랜잭션에서 사용하려고하면 교착 상태가 발생합니다 (Aaron의 게시물-마지막 링크에 연결된 내 버그 보고서 참조). 이 해결 방법은 작동하지 않습니다 (입력 문을 실행하기 전에 열린 트랜잭션을 커밋하는 것과 같은 멍청한 짓을하지 않는다고 가정).
Jon Seigel

-1

누군가 다른 것을 알지 못한다면 단일 거래에서 이것을 할 수있는 방법이 없다고 생각합니다. 나는 이것이 버그라고 생각하지 않습니다.

먼저 형식을 만들 때 스키마 수정 잠금 (Sch-M)을 수행해야합니다. 트랜잭션을 커밋하지 않기 때문에 잠금은 열린 상태로 유지됩니다. 그런 다음 동일한 트랜잭션에서 해당 유형의 변수를 선언하려고합니다. 스키마 안정성 잠금 (Sch-S)을 시도합니다. 이 두 유형은 동일한 객체에서 동시에 호환되지 않습니다. 트랜잭션이 동일하기 때문에 SQL은 트랜잭션이 열려있는 동안 Sch-S를 부여 할 수 없으므로 교착 상태로 처리합니다.

각 배치를 한 번에 하나씩 실행하고 변수를 선언하려고하면 sys.dm_tran_locks를 선택하십시오. Sch-M을 유지하고 동일한 객체에서 Sch-S를 기다리는 동일한 프로세스가 표시됩니다.


3
유형이 호환되지 않지만 동일한 프로세스가 기다릴 필요가 없다고 생각했습니다. 예를 들어, 테이블에 열을 추가 한 다음 동일한 트랜잭션에서 사용할 수 있습니다.
Michael J Swart

3
잠금 관리자는 프로세스가 이미 리소스에 대해 (실제로 더 강력한) 잠금을 보유하고 있으며 프로세스가 기다릴 필요가 없다는 것을 알아야합니다. 모든 행을 먼저 업데이트 한 다음 동일한 상황에서 다시 읽을 수 있습니다.
Sebastian Meine
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.