sourcecode

SQL Server 2005의 교착 상태 진단

copyscript 2023. 7. 8. 11:07
반응형

SQL Server 2005의 교착 상태 진단

Stack Overflow SQL Server 2005 데이터베이스에서 위험하지만 드물게 교착 상태가 발생합니다.

프로파일러를 첨부하고, 교착 상태 문제 해결에 대한 이 훌륭한 기사를 사용하여 추적 프로파일을 설정하고, 많은 예를 캡처했습니다.이상한 것은 교착 상태에 빠진 쓰기가 항상 같다는 것입니다.

UPDATE [dbo].[Posts]
SET [AnswerCount] = @p1, [LastActivityDate] = @p2, [LastActivityUserId] = @p3
WHERE [Id] = @p0

다른 교착 상태의 문장은 다양하지만, 그것은 일반적으로 게시물 표를 단순하게 읽는 것입니다.이 녀석은 항상 교착 상태에서 죽습니다.여기 예가 있어요.

SELECT
[t0].[Id], [t0].[PostTypeId], [t0].[Score], [t0].[Views], [t0].[AnswerCount], 
[t0].[AcceptedAnswerId], [t0].[IsLocked], [t0].[IsLockedEdit], [t0].[ParentId], 
[t0].[CurrentRevisionId], [t0].[FirstRevisionId], [t0].[LockedReason],
[t0].[LastActivityDate], [t0].[LastActivityUserId]
FROM [dbo].[Posts] AS [t0]
WHERE [t0].[ParentId] = @p0

완전히 명확하게 말하자면, 쓰기/쓰기 교착 상태가 아니라 읽기/쓰기 교착 상태가 보입니다.

현재 LINQ와 매개 변수화된 SQL 쿼리가 혼합되어 있습니다.는 습니다했추를 했습니다.with (nolock)모든 SQL 쿼리에 적용됩니다.이것은 일부 사람들에게 도움이 되었을 수 있습니다.또한 어제 제가 수정한 배지 쿼리는 (매우) 제대로 작성되지 않았습니다. 매번 실행하는 데 20초 이상이 걸렸고, 그 위에서 매 분마다 실행되었습니다.저는 이것이 잠금 문제의 원인이 되기를 바라고 있었습니다!

안타깝게도, 2시간 전에 또 다른 교착 상태 오류가 발생했습니다.동일한 증상, 동일한 범인이 기록합니다.

정말 이상한 것은 위에 보이는 잠금 쓰기 SQL 문이 매우 특정한 코드 경로의 일부라는 것입니다.새 응답이 질문에 추가된 경우에만 실행됩니다. 새 응답 수와 마지막 날짜/사용자로 상위 질문을 업데이트합니다.이것은 분명히 우리가 수행하고 있는 엄청난 수의 읽기와 비교했을 때 그리 흔한 일이 아닙니다!제가 아는 한, 우리는 앱 어디에서도 엄청난 수의 쓰기를 하지 않습니다.

NOLOCK이 일종의 거대한 해머라는 것은 알고 있지만, 여기서 실행되는 대부분의 쿼리는 그렇게 정확할 필요가 없습니다.당신의 사용자 프로필이 몇 초가 지났어도 상관없습니까?

NOLOCK을 Linq와 함께 사용하는 것은 Scott Hanselman이 여기서 논의한 것처럼 조금 더 어렵습니다.

우리는 사용하는 것에 대해 시시덕거리고 있습니다.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

기본 데이터베이스 컨텍스트에서 모든 LINQ 쿼리에 이 세트가 포함되도록 합니다.이것이 없다면, 우리는 우리가 하는 모든 LINQ 통화(글쎄요, 대부분의 단순한 읽기 통화)를 3-4줄 트랜잭션 코드 블록으로 포장해야 합니다. 이것은 보기 흉합니다.

SQL 2005의 사소한 읽기가 쓰기에서 교착 상태에 빠질 수 있다는 것에 약간 실망한 것 같습니다.쓰기/쓰기 교착 상태가 큰 문제인 것은 알 수 있지만 읽기는 어떻습니까?우리는 여기서 은행 사이트를 운영하는 것이 아닙니다. 매번 완벽한 정확성이 필요한 것도 아닙니다.

아이디어? 생각?


모든 작업에 대해 새 LINQ to SQL DataContext 개체를 인스턴스화하고 있습니까? 아니면 모든 호출에 대해 동일한 정적 컨텍스트를 공유하고 있습니까?

제레미, 기본 컨트롤러에서 정적 데이터 컨텍스트를 대부분 공유합니다.

private DBContext _db;
/// <summary>
/// Gets the DataContext to be used by a Request's controllers.
/// </summary>
public DBContext DB
{
    get
    {
        if (_db == null)
        {
            _db = new DBContext() { SessionName = GetType().Name };
            //_db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
        }
        return _db;
    }
}

모든 컨트롤러에 대해 또는 페이지별로 새 컨텍스트를 생성할 것을 권장합니까? 아니면 더 자주 생성할 것을 권장합니까?

MSDN에 따라:

http://msdn.microsoft.com/en-us/library/ms191242.aspx

읽기 전용 스냅샷 또는 스냅샷 분리 허용 데이터베이스 옵션이 설정되어 있으면 데이터베이스에서 수행되는 모든 데이터 수정에 대한 논리적 복사본(버전)이 유지됩니다.특정 트랜잭션에 의해 행이 수정될 때마다 Database Engine 인스턴스는 이전에 커밋된 행 이미지의 버전을 tempdb에 저장합니다.각 버전에는 변경한 트랜잭션의 트랜잭션 시퀀스 번호가 표시됩니다.수정된 행의 버전은 링크 목록을 사용하여 연결됩니다.최신 행 값은 항상 현재 데이터베이스에 저장되고 tempdb에 저장된 버전의 행에 연결됩니다.

단기 실행 트랜잭션의 경우 수정된 행의 버전이 tempdb 데이터베이스의 디스크 파일에 기록되지 않고 버퍼 풀에 캐시될 수 있습니다.버전화된 행의 필요성이 오래 지속되지 않으면 버퍼 풀에서 삭제되므로 I/O 오버헤드가 발생하지 않을 수 있습니다.

추가 오버헤드에 대해 약간의 성능 저하가 있는 것으로 보이지만 무시할 수도 있습니다.우리는 확실히 하기 위해 테스트를 해야 합니다.

꼭 필요한 경우가 아니면 이 옵션을 설정하고 코드 쿼리에서 모든 NOLOCK을 제거합니다.데이터베이스 트랜잭션 격리 수준을 해결하기 위해 데이터베이스 컨텍스트 처리기에서 글로벌 방법을 사용하는 것은 문제 해결에 도움이 됩니다.NOLOOCKs는 데이터 계층의 근본적인 문제를 은폐하고 신뢰할 수 없는 데이터를 선택하는 결과를 초래할 수 있으며, 여기서 행 자동 선택/업데이트 버전 지정이 해결책으로 나타납니다.

ALTER Database [StackOverflow.Beta] SET READ_COMMITTED_SNAPSHOT ON

잠금읽기를 사용하지 않는 것은 미끄러운 경사입니다.교착 상태가 발생하는 이유를 먼저 이해하지 못하면 절대 사용해서는 안 됩니다."모든 SQL 쿼리에 (잠금 없음)을 추가했습니다."라고 말하면 걱정이 됩니다.모든 곳에 잠금 기능이 없는 상태로 추가해야 하는 것은 데이터 계층에 문제가 있다는 확실한 신호입니다.

업데이트 문 자체가 조금 문제가 있어 보입니다.트랜잭션의 초기에 카운트를 결정하시겠습니까, 아니면 개체에서 카운트를 추출하시겠습니까? AnswerCount = AnswerCount+1질문이 추가되면 이 문제를 처리하는 더 나은 방법이 될 수 있습니다.그러면 정확한 카운트를 얻기 위해 트랜잭션이 필요하지 않고 잠재적으로 노출되는 동시성 문제에 대해 걱정할 필요가 없습니다.

을 하지 이러한 교착 상태 중는 많은작읽활지하않이유교고다러형니것쉬입한의사착는하하용상방중는운나법는해태하결문제업성화를를기없이운러더▁one▁without▁issue▁to많▁is다▁type니▁this▁use▁of▁to은▁way것▁around를 사용하는 것입니다."Snapshot Isolation Mode"(SQL 2005의 새로운 기능)을 사용하면 항상 마지막으로 수정되지 않은 데이터를 완전히 읽을 수 있습니다.또한 교착 상태에 빠진 문을 적절하게 처리하려면 매우 쉽게 캐치하고 재시도할 수 있습니다.

OP 질문은 이 문제가 발생한 이유를 묻는 것이었습니다.이 게시물은 다른 사람들이 해결할 수 있는 해결책은 남겨둔 채 그것에 답하기를 희망합니다.

이것은 아마도 인덱스와 관련된 문제일 것입니다.예를 들어, Posts 테이블에 상위 항목을 포함하는 비클러스터형 인덱스 X가 있다고 가정합니다.업데이트 중인 필드의 ID 및 하나 이상(응답 수, 마지막 활동 날짜, 마지막 활동 사용자 ID).

SELECT cmd가 인덱스 X에 대해 공유 읽기 잠금을 수행하여 ParentId로 검색한 다음 나머지 열을 가져오려면 클러스터된 인덱스에 대해 공유 읽기 잠금을 수행하고 UPDATE cmd는 클러스터된 인덱스에 대해 쓰기 전용 잠금을 수행하고 인덱스 X를 업데이트하려면 쓰기 전용 잠금을 수행해야 하는 경우 교착 상태가 발생합니다.

이제 A는 X를 잠그고 Y를 얻으려고 하는 반면, B는 Y를 잠그고 X를 얻으려고 하는 상황이 발생합니다.

물론, 우리는 OP가 실제로 이것이 원인인지 확인하기 위해 어떤 인덱스가 실행 중인지에 대한 더 많은 정보로 그의 게시물을 업데이트해야 합니다.

저는 이 질문과 수행자가 대답하는 것에 대해 상당히 불편합니다."이 마법의 먼지를 마셔보세요!"라는 말이 많습니다.그 마법의 먼지는 안돼요!"

잠금을 분석하고 어떤 유형의 잠금이 교착 상태인지 확인한 곳은 없습니다.

당신이 표시한 것은 교착 상태가 아닌 일부 잠금이 발생한다는 것입니다.

SQL 2005에서는 다음을 사용하여 어떤 잠금이 해제되는지에 대한 자세한 정보를 얻을 수 있습니다.

DBCC TRACEON (1222, -1)

교착 상태가 발생하면 더 나은 진단을 받을 수 있습니다.

모든 작업에 대해 새 LINQ to SQL DataContext 개체를 인스턴스화하고 있습니까? 아니면 모든 호출에 대해 동일한 정적 컨텍스트를 공유하고 있습니까?저는 원래 후자의 방법을 시도했는데, 제가 기억하는 바로는 DB에 원치 않는 잠금이 발생한 것으로 알고 있습니다.이제 모든 원자력 작업에 대한 새로운 컨텍스트를 만듭니다.

집을 불태워 파리를 잡기 전에 프로파일러로 캡처했어야 하는 교착 상태 그래프를 보는 것이 좋습니다.

교착 상태에는 (최소한) 2개의 잠금이 필요합니다.연결 1에는 잠금 A가 있고, 연결 2에는 잠금 B가 있고, 그 반대의 경우도 있습니다.이것은 해결할 수 없는 상황이고, 누군가는 양보해야 합니다.

지금까지 보여주신 내용은 SQL Server가 하루 종일 기꺼이 수행하는 단순 잠금으로 해결됩니다.

나는 당신(또는 LINQ)이 그 안에 있는 UPDATE 문으로 거래를 시작하고 사전에 다른 정보를 선택하고 있다고 생각합니다.그러나 각 스레드가 보유한 잠금을 찾으려면 교착 그래프를 통해 역추적한 다음 프로파일러를 통해 해당 잠금을 허용한 문을 찾아야 합니다.

저는 이 퍼즐을 완료하기 위해 적어도 4개의 문장이 있을 것으로 예상합니다(또는 여러 개의 잠금을 취하는 문장 - 아마도 게시물 표에 트리거가 있을 것인가?).

당신의 사용자 프로필이 몇 초가 지났어도 상관없습니까?

아니요 - 그것은 완벽하게 받아들일 수 있습니다.기본 트랜잭션 격리 수준을 설정하는 것이 가장 좋은 방법일 것입니다.

일반적인 읽기/쓰기 교착 상태는 인덱스 순서 액세스에서 발생합니다.읽기(T1)는 인덱스 A에서 행을 찾은 다음 인덱스 B(일반적으로 군집화됨)에서 투영된 열을 찾습니다.쓰기(T2)는 색인 B(클러스터)를 변경한 다음 색인 A를 업데이트해야 합니다.T1은 A에 S-Lock이 있고, B에 S-Lock이 있고, T2는 B에 X-Lock이 있고, A에 U-Lock이 있습니다.교착 상태, 퍼프.T1이 죽었습니다.이는 OLTP 트래픽이 많고 인덱스가 약간 많은 환경에서 널리 사용됩니다. :).해결책은 읽기가 A에서 B로 점프할 필요가 없도록 하거나(즉, A에 열 포함 또는 투영 목록에서 열 제거), T2가 B에서 A로 점프할 필요가 없도록 하는 것입니다(인덱스 열 업데이트 안 함).유감스럽게도, 린크는 여기서 당신의 친구가 아닙니다...

@Jeff - 저는 이에 대한 전문가는 아니지만, 거의 모든 상담에서 새로운 맥락을 인스턴스화하여 좋은 결과를 얻었습니다.ADO를 사용하는 모든 통화에서 새 Connection 개체를 만드는 것과 유사하다고 생각합니다.어쨌든 연결 풀링은 계속 사용되므로 오버헤드는 생각보다 나쁘지 않습니다.

저는 다음과 같은 글로벌 정적 도우미를 사용합니다.

public static class AppData
{
    /// <summary>
    /// Gets a new database context
    /// </summary>
    public static CoreDataContext DB
    {
        get
        {
            var dataContext = new CoreDataContext
            {
                DeferredLoadingEnabled = true
            };
            return dataContext;
        }
    }
}

그리고 나서 저는 다음과 같은 일을 합니다.

var db = AppData.DB;

var results = from p in db.Posts where p.ID = id select p;

업데이트에 대해서도 마찬가지입니다.어쨌든, 저는 당신만큼 트래픽이 많지는 않지만, 소수의 사용자들과 함께 초기에 공유 DataContext를 사용했을 때 분명히 약간의 잠금을 받고 있었습니다.보장은 없지만, 시도해 볼 만한 가치가 있을지도 모릅니다.

업데이트: 코드를 보면 특정 컨트롤러 인스턴스의 수명 동안만 데이터 컨텍스트를 공유할 수 있습니다. 컨트롤러 내의 여러 호출에서 동시에 사용되지 않는 한 기본적으로 문제가 없는 것 같습니다.이 주제에 대한 스레드에서 Scott Gu는 다음과 같이 말했습니다.

컨트롤러는 단일 요청에 대해서만 작동하므로 요청 처리가 끝나면 가비지 수집(즉, 데이터 컨텍스트가 수집됨)됩니다.

어쨌든, 그것은 아닐 수도 있지만, 다시 한 번 시도해 볼 가치가 있을 것입니다. 아마도 부하 테스트와 함께 말입니다.

Q. 스토리지를 저장하는 이유는 무엇입니까?AnswerCount에 시대에Posts첫번째 자리에?

다른 은 적인접방다쓰음대에 "한를되기리돌 "는제기하것 "입거니다대 "에back"을입니다.Posts저지않음테이블써로를 AnswerCount필요에 따라 게시물에 대한 답변 수를 동적으로 계산합니다.

예, 이는 추가 쿼리를 실행 중임을 의미합니다.

SELECT COUNT(*) FROM Answers WHERE post_id = @id

또는 일반적으로(홈 페이지에 대해 표시하는 경우):

SELECT p.post_id, 
     p.<additional post fields>,
     a.AnswerCount
FROM Posts p
    INNER JOIN AnswersCount_view a
    ON <join criteria>
WHERE <home page criteria>

하지만 이것은 일반적으로 다음과 같은 결과적으로 이어집니다.INDEX SCAN 자원을 사용하는 이 더 일 수 .READ ISOLATION.

고양이 가죽을 벗기는 방법은 여러 가지가 있습니다.데이터베이스 스키마의 비정규화를 너무 일찍 수행하면 확장성 문제가 발생할 수 있습니다.

READ_COMMITED_SNAPSHOT를 기본값이 아닌 on으로 설정해야 합니다.MVCC 의미론을 제공합니다.Oracle에서 기본적으로 사용하는 것과 동일합니다.MVCC 데이터베이스를 보유하는 것은 매우 유용하며, 사용하지 않는 것은 미친 짓입니다.이렇게 하면 트랜잭션 내에서 다음을 실행할 수 있습니다.

업데이트 사용자 이름 설정 = 'foobar'; //1년 동안 절전 모드로 전환합니다.

한편, 위 사항을 준수하지 않고 모든 사람이 해당 테이블에서 계속 선택할 수 있습니다.만약 여러분이 MVCC에 익숙하지 않다면, 여러분은 MVCC 없이 살 수 있었다는 것에 충격을 받을 것입니다.진짜로.

기본값을 커밋되지 않은 읽기로 설정하는 것은 좋은 생각이 아닙니다.당신의 의지는 의심할 여지 없이 모순을 초래하고 당신이 지금 가지고 있는 것보다 더 나쁜 문제로 끝납니다.스냅샷 분리는 잘 작동할 수 있지만 SQL 서버의 작동 방식이 크게 변경되어 tempdb에 큰 부하가 걸립니다.

T-SQL에서 try-catch(T-SQL에서)를 사용하여 교착 상태를 탐지해야 합니다.이 경우 쿼리를 다시 실행합니다.이것은 표준 데이터베이스 프로그래밍 방법입니다.

Paul Nielson의 Sql Server 2005 Bible에는 이 기술의 좋은 예가 있습니다.

사용하는 빠른 템플릿은 다음과 같습니다.

-- Deadlock retry template

declare @lastError int;
declare @numErrors int;

set @numErrors = 0;

LockTimeoutRetry:

begin try;

-- The query goes here

return; -- this is the normal end of the procedure

end try begin catch
    set @lastError=@@error
    if @lastError = 1222 or @lastError = 1205 -- Lock timeout or deadlock
    begin;
        if @numErrors >= 3 -- We hit the retry limit
        begin;
            raiserror('Could not get a lock after 3 attempts', 16, 1);
            return -100;
        end;

        -- Wait and then try the transaction again
        waitfor delay '00:00:00.25';
        set @numErrors = @numErrors + 1;
        goto LockTimeoutRetry;

    end;

    -- Some other error occurred
    declare @errorMessage nvarchar(4000), @errorSeverity int
    select    @errorMessage = error_message(),
            @errorSeverity = error_severity()

    raiserror(@errorMessage, @errorSeverity, 1)

    return -100
end catch;    

과거에는 모든 쿼리와 업데이트가 동일한 순서로 리소스(표)에 액세스하도록 했습니다.

즉, 하나의 쿼리가 표 1, 표 2의 순서로 업데이트되고 다른 쿼리가 표 2, 표 1의 순서로 업데이트되면 교착 상태가 나타날 수 있습니다.

LINQ를 사용하고 있기 때문에 업데이트 순서를 변경할 수 있는지 잘 모르겠습니다.하지만 그것은 살펴봐야 할 것입니다.

당신의 사용자 프로필이 몇 초가 지났어도 상관없습니까?

몇 초 정도면 충분할 것 같습니다.어쨌든 엄청난 수의 사람들이 동시에 답을 제출하지 않는 한 그렇게 오래 걸리지는 않을 것 같습니다.

저는 이것에 대해 제레미의 의견에 동의합니다.각 컨트롤러에 대해 또는 페이지당 새 데이터 컨텍스트를 만들어야 하는지 묻는 메시지가 나타납니다. 저는 모든 독립 쿼리에 대해 새 데이터 컨텍스트를 만드는 경향이 있습니다.

저는 현재 당신처럼 정적 컨텍스트를 구현하던 솔루션을 구축하고 있으며, 스트레스 테스트 중 서버의 야수(백만 명 이상)에게 수많은 요청을 던졌을 때 랜덤 읽기/쓰기 잠금도 받았습니다.

쿼리당 LINQ 수준에서 다른 데이터 컨텍스트를 사용하도록 전략을 변경하고 SQL 서버가 연결 풀링 마법을 사용할 수 있다고 믿자마자 잠금이 사라지는 것 같았습니다.

물론 시간적인 압박감이 있었기 때문에 여러 가지를 동시에 시도해 보기 때문에 그것이 해결됐다고 100% 확신할 수는 없지만, 저는 높은 수준의 자신감을 가지고 있습니다 - 그렇게 말하죠.

더티 읽기를 구현해야 합니다.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

쿼리에 완벽한 트랜잭션 무결성이 필요하지 않다면 동시성이 높은 테이블에 액세스할 때 더티 읽기를 사용해야 합니다.저는 당신의 포스트 테이블이 그것들 중 하나일 것이라고 생각합니다.

이것은 소위 "팬텀 읽기"라고 불리는 것을 제공할 수 있는데, 이것은 당신의 쿼리가 커밋되지 않은 트랜잭션의 데이터에 작용하는 것입니다.

우리는 여기서 은행 사이트를 운영하지 않습니다. 매번 완벽한 정확성이 필요한 것은 아닙니다.

더티 읽기를 사용합니다.완벽한 정확도를 제공하지는 않지만 고정 문제를 해결해야 한다는 점에서 귀하의 말이 맞습니다.

그것이 없다면, 우리는 우리가 하는 모든 LINQ 통화(글쎄요, 대부분의 단순한 읽기 통화)를 3-4줄 트랜잭션 코드 블록으로 포장해야 하는데, 이것은 보기 흉합니다.

기본 데이터베이스 컨텍스트에서 더티 읽기를 구현하는 경우 트랜잭션 무결성이 필요한 경우 항상 더 높은 분리 수준을 사용하여 개별 호출을 래핑할 수 있습니다.

그렇다면 재시도 메커니즘을 구현하는 데 어떤 문제가 있습니까?교착 상태가 발생할 가능성은 항상 있을 것이므로 이를 식별하고 다시 시도하는 논리를 갖는 것이 어떻습니까?

적어도 다른 옵션 중 일부는 재시도 시스템이 거의 시작되지 않을 때 항상 취하는 성능 페널티를 도입하지 않을까요?

또한, 당신이 드물게 되는 상황에 빠지지 않도록 재시도가 발생할 때 어떤 종류의 기록을 잊지 마세요.

이제 제레미의 답변을 보니 각 데이터 작업에 새로운 DataContext를 사용하는 것이 가장 좋은 방법이라는 말을 들은 것 같습니다.Rob Conery는 DataContext에 대해 여러 개의 게시물을 작성했으며, 싱글톤을 사용하지 않고 항상 뉴스를 제공합니다.

여기 비디오에 사용한 패턴이 있습니다.표시(CodePlex의 소스 보기에 대한 링크):

using System.Configuration;
namespace VideoShow.Data
{
  public class DataContextFactory
  {
    public static VideoShowDataContext DataContext()
    {
        return new VideoShowDataContext(ConfigurationManager.ConnectionStrings["VideoShowConnectionString"].ConnectionString);
    }
    public static VideoShowDataContext DataContext(string connectionString)
    {
        return new VideoShowDataContext(connectionString);
    }
  }
}

그런 다음 서비스 레벨(또는 업데이트의 경우 훨씬 더 세분화됨)에서 다음을 수행합니다.

private VideoShowDataContext dataContext = DataContextFactory.DataContext();

public VideoSearchResult GetVideos(int pageSize, int pageNumber, string sortType)
{
  var videos =
  from video in DataContext.Videos
  where video.StatusId == (int)VideoServices.VideoStatus.Complete
  orderby video.DatePublished descending
  select video;
  return GetSearchResult(videos, pageSize, pageNumber);
}

격리 수준을 커밋되지 않은 읽기로 설정하는 것이 다른 쿼리에 악영향을 미치지 않는 한 Greg의 의견에 동의해야 합니다.

데이터베이스 수준에서 설정하면 다음과 같은 쿼리에 어떤 영향을 미치는지 알고 싶습니다.

Begin Tran
Insert into Table (Columns) Values (Values)
Select Max(ID) From Table
Commit Tran

제 프로필이 몇 분이라도 오래된 것이라면 저는 괜찮습니다.

읽기가 실패한 후 다시 시도하시겠습니까?많은 랜덤 읽기를 실행할 때 몇 개는 읽을 수 없을 때 적중할 수 있습니다.제가 사용하는 대부분의 애플리케이션은 읽기 수에 비해 쓰기 횟수가 매우 적으며, 읽기 횟수가 실제보다 훨씬 적을 것이라고 확신합니다.

"Read Uncommitted"를 구현해도 문제가 해결되지 않으면 처리에 대해 자세히 알지 못한 채 도움을 주기가 어렵습니다.이 동작에 도움이 되는 다른 조정 옵션이 있을 수 있습니다.MSSQL 전문가가 구조에 나서지 않는 한 공급업체에 문제를 제출할 것을 권장합니다.

모든 것을 계속 조정할 것입니다. 디스크 하위 시스템의 성능은 어떻습니까?평균 디스크 대기열 길이는 얼마입니까?I/O가 백업 중인 경우, 실제 문제는 교착 상태에 있는 이 두 쿼리가 아니라 시스템을 병목 상태로 만드는 또 다른 쿼리일 수 있습니다. 20초가 걸린 쿼리를 언급했는데 다른 쿼리도 있습니까?

오랫동안 실행된 쿼리를 단축하는 데 초점을 맞추면 교착 상태 문제가 사라질 것입니다.

동일한 문제가 있으며 "격리"를 사용할 수 없습니다.레벨 = 격리서버에 DTS(디지털 스로틀 및 시프트)가 설정되어 있지 않기 때문에 트랜잭션 범위에서 "Level.ReadUncommitted"(레벨.ReadUncommitted)입니다.

그것이 제가 확장 방법으로 한 일입니다.

public static void SetNoLock(this MyDataContext myDS)
{
    myDS.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}

따라서 중요 동시성 테이블을 사용하는 선택자의 경우 다음과 같은 "nolock"을 활성화합니다.

using (MyDataContext myDS = new MyDataContext())
{
   myDS.SetNoLock();

   //  var query = from ...my dirty querys here...
}

제안을 환영합니다!

언급URL : https://stackoverflow.com/questions/20047/diagnosing-deadlocks-in-sql-server-2005

반응형