복붙노트

[SQL] 는 SQL 트랜잭션의 동시성 처리

SQL

는 SQL 트랜잭션의 동시성 처리

나는 약 나는이 응용 프로그램의 동시성 요구 사항을 설계해야 ASP.NET 및 SQL Server 2005을 사용하여 프로젝트를 시작하는 오전 가정하자. 나는 각 테이블에 타임 스탬프 열을 추가 할 계획입니다. 테이블을 업데이트하는 동안이 선택되었을 때 나는, 타임 스탬프 열이 동일한 지 확인합니다.

이 방법은 충분할 것인가? 또는 어떤 상황에서도이 방법에 대한 단점이있다?

제발 조언.

감사

Lijo

해결법

  1. ==============================

    1.우선 당신이 당신의 질문에 설명하는 방법은 내 의견으로는 데이터베이스로 MS SQL와 ASP.NET 응용 프로그램에 대한 최선의 방법입니다. 데이터베이스에는 잠금이 없습니다. 이 웹 클라이언트와 같은 영구적으로 분리 클라이언트와 완벽합니다.

    우선 당신이 당신의 질문에 설명하는 방법은 내 의견으로는 데이터베이스로 MS SQL와 ASP.NET 응용 프로그램에 대한 최선의 방법입니다. 데이터베이스에는 잠금이 없습니다. 이 웹 클라이언트와 같은 영구적으로 분리 클라이언트와 완벽합니다.

    하나는 일부 답변에서 읽을 수있는 방법, 용어의 오해가있다. 우리는 평균 마이크로 소프트 SQL 서버 2008 이상을 사용하면 데이터베이스를 유지합니다. 당신은 MS SQL 서버 2008 설명서에서 주제 "rowversion (Transact-SQL)를"열 경우 다음 발견 할 것이다 :

    그래서 타임 스탬프 데이터 형식은 MS SQL에 대한 rowversion 데이터 유형에 대한 동의어입니다. 그것은 모든 데이터베이스에 내부적으로 존재하고 @@ DBTS으로 볼 수있는 카운터를 64 비트 보유하고 있습니다. 데이터베이스의 한 테이블에 한 행의 수정 후, 카운터가 증가 될 것이다.

    내가 질문을 읽으면서 나는 형 rowversion 데이터의 열 이름으로 "타임 스탬프"를 참조하십시오. 나는 개인적으로 이름 RowUpdateTimeStamp을 선호합니다. AzManDB에서 나는 그런 이름을 볼 수 있었다 (DB로 저장 (Store)와 마이크로 소프트 권한 부여 관리자를 참조). 때때로 (트리거와 관련하여) 계층 RowUpdateTimeStamp 구조를 추적하는 것이 ChildUpdateTimeStamp을 사용 하였다.

    나는 내 마지막 프로젝트에이 방법을 구현하고 매우 행복합니다. 일반적으로 당신은 다음을 수행 :

    SELECT s.Id AS Id
        ,s.Name AS SoftwareName
        ,m.Name AS ManufacturerName
        ,CASE WHEN s.RowUpdateTimeStamp > m.RowUpdateTimeStamp
              THEN s.RowUpdateTimeStamp 
              ELSE m.RowUpdateTimeStamp 
         END AS RowUpdateTimeStamp 
    FROM dbo.Software AS s
        INNER JOIN dbo.Manufacturer AS m ON s.Manufacturer_Id=m.Id
    

    또는 데이터는 다음과 같이 캐스팅 할

    SELECT s.Id AS Id
        ,s.Name AS SoftwareName
        ,m.Name AS ManufacturerName
        ,CASE WHEN s.RowUpdateTimeStamp > m.RowUpdateTimeStamp
              THEN CAST(s.RowUpdateTimeStamp AS bigint)
              ELSE CAST(m.RowUpdateTimeStamp AS bigint)
         END AS RowUpdateTimeStamp 
    FROM dbo.Software AS s
        INNER JOIN dbo.Manufacturer AS m ON s.Manufacturer_Id=m.Id
    

    BIGINT, C 번호의 대응 ULONG 데이터 형식으로 RowUpdateTimeStamp를 보유한다. 당신이 많은 테이블에서 OUTER 관절이나 관절을 만드는 경우, 모든 테이블의 구조 MAX (RowUpdateTimeStamp)는 조금 더 복잡 볼 수 있습니다. MS SQL은 MAX (A, B, C, D, E)에 대응하는 구조와 같은 기능을 지원할 수 없기 때문에 다음과 같다 :

    (SELECT MAX(rv)
     FROM (SELECT table1.RowUpdateTimeStamp AS rv
          UNION ALL SELECT table2.RowUpdateTimeStamp
          UNION ALL SELECT table3.RowUpdateTimeStamp
          UNION ALL SELECT table4.RowUpdateTimeStamp
          UNION ALL SELECT table5.RowUpdateTimeStamp) AS maxrv) AS RowUpdateTimeStamp
    
    CREATE PROCEDURE dbo.spSoftwareUpdate
        @Id int,
        @SoftwareName varchar(100),
        @originalRowUpdateTimeStamp bigint, -- used for optimistic concurrency mechanism
        @NewRowUpdateTimeStamp bigint OUTPUT
    AS
    BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        -- ExecuteNonQuery() returns -1, but it is not an error
        -- one should test @NewRowUpdateTimeStamp for DBNull
        SET NOCOUNT ON;
    
        UPDATE dbo.Software
        SET Name = @SoftwareName
        WHERE Id = @Id AND RowUpdateTimeStamp <= @originalRowUpdateTimeStamp
    
        SET @NewRowUpdateTimeStamp = (SELECT RowUpdateTimeStamp
                                      FROM dbo.Software
                                      WHERE (@@ROWCOUNT > 0) AND (Id = @Id));
    END
    

    dbo.spSoftwareDelete의 코드는 같은 같은 절차 모양을 저장. 당신이 NOCOUNT에 전환하지 않는 경우 DBConcurrencyException 자동으로 시나리오에 많이 발생 생성 할 수 있습니다. 비주얼 스튜디오는 TableAdapter에 또는 데이터 어댑터의 고급 옵션에서 "사용 낙관적 동시성"체크 박스처럼 낙관적 동시성을 사용하는 당신에게 가능성을 제공합니다.

    당신이 dbo.spSoftwareUpdate 저장 프로 시저 carful 보면 당신은 내가 WHERE 대신 RowUpdateTimeStamp = @originalRowUpdateTimeStamp의에 RowUpdateTimeStamp <= @originalRowUpdateTimeStamp를 사용하는 것을 발견 할 것이다. 내가 어떻게 그렇게 때문에, 등과 같은 하나 개의 테이블에서 일반적으로 MAX (RowUpdateTimeStamp)로 구성되어 클라이언트를 가지고 @originalRowUpdateTimeStamp의 값. 그래서 그 RowUpdateTimeStamp <@originalRowUpdateTimeStamp 수 있습니다. 어느 쪽이든 당신은 엄격한 평등을 사용 = 당신이 SELECT 문 또는 사용 <에 사용 된 것과 같은 복잡한 문을 가입 여기에 재현한다 = 나 같은 구조 및 숙박 정확한 이전과 같은 안전합니다.

    그런데, 하나는 데이터와 함께 클라이언트에 HTTP 헤더에 전송 할 수 RowUpdateTimeStamp를 기반으로있는 ETag을 위해 아주 좋은 값을 구성 할 수 있습니다. Etag입니다 사용하면 클라이언트 측 캐싱 지능형 데이터를 구현할 수 있습니다.

    나는 여기에 전체 코드를 작성할 수는 없지만 인터넷에서 많은 예를 찾을 수 있습니다. 난 단지 rowversion에 따라 내 의견 사용 낙관적 동시성에서 ASP.NET 시나리오의 대부분을위한 최선의 방법이라고 한 번 더 반복합니다.

  2. ==============================

    2.SQL 서버에서 상황의 유형에 대한 권장되는 방법은 해당 행의 필드 중 하나를 변경 한 경우하는지 확인하기 위해 유형 'rowversion'사용의 열을 생성하는 것입니다.

    SQL 서버에서 상황의 유형에 대한 권장되는 방법은 해당 행의 필드 중 하나를 변경 한 경우하는지 확인하기 위해 유형 'rowversion'사용의 열을 생성하는 것입니다.

    SQL Server는 행 변화 값 (또는 새로운 행이 삽입 된) 경우의 rowversion 열은 자동으로 다른 값으로 업데이트 할 것을 보장합니다. 데이터베이스가 당신을 위해이 문제를 해결할시키는 것은 훨씬 더 안정적인 스스로 일을하려고보다.

    당신의 업데이트 문에서 당신은 단순히 절은 rowversion 값이 먼저 행을 검색 할 때와 동일 있는지 확인하기 위해 어디를 추가해야합니다. 그렇지 않으면, 다른 사람이 행을 변경 (예 : 그것의 더러운)

    또한, 해당 페이지에서 :

  3. ==============================

    3.나는 동시성이 같은 데이터베이스에서 처리되어야 함을 모르겠어요. 자신이 할 수 있어야 데이터베이스는 분리 및 트랜잭션 동작을 관리하지만, 스레딩 동작은 코드에서 수행되어야한다.

    나는 동시성이 같은 데이터베이스에서 처리되어야 함을 모르겠어요. 자신이 할 수 있어야 데이터베이스는 분리 및 트랜잭션 동작을 관리하지만, 스레딩 동작은 코드에서 수행되어야한다.

  4. ==============================

    4.rowversion 제안은 내가 말을하지만 그 타임 스탬프가 곧 중단 될 예정보고 실망 올바른 것입니다. 내 OLD 응용 프로그램의 일부는 다음 동시성을 확인하는 여러 가지 이유가 이것을 사용하고 있습니다.

    rowversion 제안은 내가 말을하지만 그 타임 스탬프가 곧 중단 될 예정보고 실망 올바른 것입니다. 내 OLD 응용 프로그램의 일부는 다음 동시성을 확인하는 여러 가지 이유가 이것을 사용하고 있습니다.

  5. from https://stackoverflow.com/questions/2658443/concurrency-handling-of-sql-transactrion by cc-by-sa and MIT license