분명히, 내 CLR 어셈블리 기능이 교착 상태를 유발하고 있습니까?


9

우리의 응용 프로그램은 Oracle 데이터베이스 또는 Microsoft SQL Server 데이터베이스와 동일하게 작동해야합니다. 이를 용이하게하기 위해 쿼리 구문을 균질화하기 위해 소수의 UDF를 작성했습니다. 예를 들어, SQL Server에는 GETDATE ()가 있고 Oracle에는 SYSDATE가 있습니다. 그들은 같은 기능을 수행하지만 다른 단어입니다. 우리는 두 플랫폼에 대해 NOW ()라는 랩퍼 UDF를 작성했으며,이 플랫폼은 관련 플랫폼 특정 구문을 공통 함수 이름으로 랩핑했습니다. 우리는 다른 기능을 가지고 있는데, 그중 일부는 본질적으로 균질화를 위해서만 존재합니다. 불행히도, 이것은 SQL Server 비용이 있습니다. 인라인 스칼라 UDF는 성능을 저하시키고 병렬 처리를 완전히 비활성화합니다. 대안으로, 동일한 목표를 달성하기 위해 CLR 어셈블리 기능을 작성했습니다. 이를 클라이언트에 배포 할 때 교착 상태가 자주 발생했습니다. 이 특정 클라이언트는 복제 및 고 가용성 기술을 사용하고 있으며 여기에 어떤 종류의 상호 작용이 있는지 궁금합니다. CLR 기능을 도입하면 이와 같은 문제가 어떻게 발생하는지 이해하지 못합니다. 참고로, 원래 스칼라 UDF 정의와 C #의 대체 CLR 정의 및 이에 대한 SQL 선언을 포함 시켰습니다. 또한 도움이된다면 제공 할 수있는 교착 상태 XML이 있습니다.

원본 UDF

CREATE FUNCTION [fn].[APAD]
(
    @Value VARCHAR(4000)
    , @tablename VARCHAR(4000) = NULL
    , @columnname VARCHAR(4000) = NULL
)

RETURNS VARCHAR(4000)
WITH SCHEMABINDING
AS

BEGIN
    RETURN LTRIM(RTRIM(@Value))
END
GO

CLR 조립 기능

[SqlFunction(IsDeterministic = true)]
public static string APAD(string value, string tableName, string columnName)
{
    return value?.Trim();
}

CLR 함수에 대한 SQL Server 선언

CREATE FUNCTION [fn].[APAD]
(
    @Value NVARCHAR(4000),
    @TableName NVARCHAR(4000),
    @ColumnName NVARCHAR(4000)
) RETURNS NVARCHAR(4000)
AS
EXTERNAL NAME ASI.fn.APAD
GO

9
결정 론적 스칼라 CLR 함수는 교착 상태에 영향을 미치지 않아야합니다. 물론 데이터베이스를 읽는 CLR 함수도 가능합니다. 질문에 교착 상태 XML을 포함시켜야합니다.
David Browne-Microsoft

답변:


7

어떤 버전의 SQL Server를 사용하고 있습니까?

얼마 전 SQL Server 2017의 동작이 약간 변경되었음을 기억합니다. 돌아가서 메모를 한 곳을 찾을 수 있는지 확인해야하지만 SQLCLR 객체에 액세스 할 때 스키마 잠금이 시작되어야한다고 생각합니다.

나는 그것을 찾고있는 동안, 당신의 접근 방식에 대해 다음과 같이 말할 것입니다.

  1. Sql*입력 매개 변수, 리턴 유형 의 유형을 사용하십시오 . SqlString대신 사용해야합니다 string. SqlString는 nullable 문자열과 매우 유사 value?하지만 ( , 그러나 SQL Server 고유의 다른 기능이 내장되어 있습니다. 모든 Sql*형식에는 Value예상 .NET 형식을 반환 하는 속성이 있습니다 (예 : SqlString.Valuereturns string, SqlInt32returns int, SqlDateTimereturns DateTime등).
  2. 교착 상태와 관련이 있는지 여부에 관계 없이이 전체 접근 방식을 사용하지 않는 것이 좋습니다. 나는 이것을 말하기 때문에 :

    1. 결정 론적 SQLCLR UDF가 병렬 계획에 참여할 수 있더라도 단순한 내장 함수를 에뮬레이트하면 성능이 저하 될 수 있습니다.
    2. SQLCLR API는 허용하지 않습니다 VARCHAR. 간단한 조작 NVARCHARVARCHAR위해 모든 것을 암시 적으로 변환 한 다음 다시 다시 변환해도 괜찮 습니까?
    3. SQLCLR API는 오버로드를 허용하지 않으므로 T-SQL 및 / 또는 PL / SQL에서 다른 서명을 허용하는 여러 버전의 함수가 필요할 수 있습니다.
    4. 오버로드를 허용하지 않는 것과 비슷하게 NVARCHAR(4000)와 사이에는 큰 차이가 있습니다 NVARCHAR(MAX). MAX유형 (서명에 단일 유형이라도 있음)은 SQLCLR 호출 MAX에 서명에 유형이 없는 것보다 두 배 오래 걸립니다. 사실에 대한 VARBINARY(MAX)VARBINARY(4000))뿐만 아니라. 따라서 다음 중 하나를 결정해야합니다.
      • NVARCHAR(MAX)API를 단순화하기 위해서만 사용 하지만 8000 바이트 이하의 문자열 데이터를 사용하는 경우 성능 저하를 가져 오거나
      • 모든 / 대부분 / 많은 문자열 함수에 대해 두 가지 변형을 작성하십시오. 하나는 MAX유형이 있고 다른 하나는없는 것입니다 (8000 바이트 이상의 문자열 데이터가 들어가거나 나가지 않을 때). 이것은 SQL # 라이브러리의 대부분의 함수에 대해 선택한 접근법입니다. Trim()하나 이상의 MAX유형 이있는 함수 와 서명 또는 결과 세트 스키마의 어느 곳에도 유형 Trim4k()이없는 버전이 MAX있습니다. "4k"버전은 절대적으로 더 효율적입니다.
    5. 질문의 예에서 주어진 기능을 에뮬레이트하지 않으려 고합니다. LTRIM그리고 RTRIM단지 트림 공간, .NET는 동안 String.Trim()공백 (적어도 공간, 탭, 줄 바꿈) 트림. 예를 들면 다음과 같습니다.

        PRINT LTRIM(RTRIM(N'      a       '));
    6. 또한 T-SQL과 C #에서 함수가 3 개의 입력 매개 변수 중 하나만 사용한다는 것을 알았습니다. 이것은 단지 개념 증명이거나 개정 된 코드입니까?

1. Sql 유형 사용에 대한 팁을 주셔서 감사합니다. 이제 변경하겠습니다. 2. 여기에는 작업을 수행해야하는 외부 세력이 있습니다. 나는 그것에 대해 흥분하지 않지만 나를 믿어 라. 그것은 대안보다 낫다. 내 원래 질문에는 왜 겉보기에 asinine 함수가 존재하고 사용되고 있는지에 대한 약간의 설명이 포함되어 있습니다.
Russ Suter

@RussSuter 다시 이해 : 외력. 나는 그 결정을 내릴 때 알려지지 않은 함정을 지적하고있었습니다. 어느 쪽이든, 내가 기억하는 몇 가지 세부 사항으로 메모를 찾거나 시나리오를 재현 할 수 없습니다. 나는 2017 년에 어셈블리에서 트랜잭션 및 호출 코드와 관련하여 확실히 변경 된 것을 기억하고 , 더 나쁜 경우에 불필요 한 변화처럼 보였으므로 실제로 화가 났으며, 테스트 한 대상에 대해 해결해야했습니다. 이전 버전에서는 괜찮습니다. 따라서 교착 상태 XML에 대한 질문에 대한 링크를 게시하십시오.
Solomon Rutzky

추가 정보에 감사드립니다. 다음은 XML에 대한 링크입니다. dropbox.com/s/n9w8nsdojqdypqm/deadlock17.xml?dl=0
Russ Suter

@RussSuter T-SQL을 인라인하여 이것을 시도 했습니까? 교착 상태 XML을 살펴보면 (한 줄이므로 모든 줄 바꿈이 어떻게 든 제거되지는 않습니다) 60과 78 세션 사이에 일련의 PAGE 잠금으로 나타납니다. 두 세션 사이에 8 페이지가 잠겨 있습니다. 다른 하나는 SPID와 5입니다. 각각 프로세스 ID가 다르므로 이는 병렬 처리의 문제입니다. 이것이 SQLCLR과 관련이 있다면, 아이러니하게도 SQLCLR이 병렬 처리를 방해하지 않는다는 사실 일 수 있습니다. 이것이 교착 상태를 나타낼 수도 있으므로 간단한 함수를 인라인으로 넣으려고했는지 묻는 이유입니다.
Solomon Rutzky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.