문제

저는 데이터베이스 테이블(MS SQL 서버에서 정규화됨)을 설계하고 소수의 사용자가 정보를 추가하고 편집하는 데 사용할 응용 프로그램용 독립형 Windows 프런트 엔드를 만들었습니다.나중에 생산 영역 전체를 검색할 수 있도록 웹 인터페이스를 추가할 예정입니다.

두 명의 사용자가 동일한 레코드 편집을 시작하면 마지막으로 업데이트를 커밋한 사용자가 '승자'가 되어 중요한 정보가 손실될 수 있다는 점이 걱정됩니다.여러 가지 해결책이 떠오르지만 더 큰 골치 아픈 일이 될지는 잘 모르겠습니다.

  1. 아무것도 하지 말고 두 명의 사용자가 동시에 같은 레코드를 편집하지 않기를 바랍니다. - 절대 그런 일이 일어나지 않을 수도 있지만 만약 그런 일이 일어난다면 어떨까요?
  2. 편집 루틴은 원본 데이터의 복사본과 업데이트를 저장한 다음 사용자가 편집을 마쳤을 때 비교할 수 있습니다.다를 경우 사용자 표시 및 업데이트 확인 - 저장하려면 두 개의 데이터 사본이 필요합니다.
  3. 마지막으로 업데이트된 DATETIME 열을 추가하고 업데이트할 때 일치하는지 확인하고, 일치하지 않으면 차이점을 표시합니다. - 각 관련 테이블에 새 열이 필요합니다.
  4. 사용자가 확인할 레코드 편집을 시작할 때 등록하고 다른 사용자가 동일한 레코드를 편집하지 못하도록 하는 편집 테이블을 만듭니다. - 사용자가 프로그램에서 충돌을 일으키면 교착 상태와 레코드가 잠기는 것을 방지하기 위해 프로그램 흐름에 대한 신중한 생각이 필요합니다.

더 나은 솔루션이 있습니까? 아니면 다음 중 하나를 선택해야 합니까?

도움이 되었습니까?

해결책

드물게 충돌이 발생할 것으로 예상되는 경우, 낙관적 동시성 아마도 최선의 방법 일 것입니다.

Scott Mitchell은 해당 패턴 구현에 대한 포괄적인 튜토리얼을 작성했습니다.
낙관적 동시성 구현

다른 팁

고전적인 접근 방식은 다음과 같습니다.

  • 각 테이블에 "잠긴" 부울 필드를 추가합니다.
  • 기본적으로 false로 설정합니다.
  • 사용자가 편집을 시작하면 다음을 수행합니다.

    • 행(또는 행을 잠글 수 없는 경우 전체 테이블)을 잠급니다.
    • 편집하려는 행의 플래그를 확인하세요.
    • 플래그가 참이면
      • 현재는 해당 행을 편집할 수 없다고 사용자에게 알립니다.
    • 또 다른
      • 플래그를 true로 설정
    • 자물쇠를 풀다

    • 레코드를 저장할 때 플래그를 다시 false로 설정하세요.

SELECT FOR UPDATE 및 이에 상응하는 기능은 미세한 시간 동안 잠금을 유지하는 것이 좋지만 거시적인 시간(예:사용자가 데이터를 로드했지만 '저장'을 누르지 않은 경우 위와 같이 낙관적 동시성을 사용해야 합니다.(나는 항상 이름이 잘못되었다고 생각합니다. 일반적으로 고려되는 유일한 대안인 '마지막 작가가 승리합니다'보다 더 비관적입니다.)

@ 마크 해리슨 :SQL Server는 해당 구문을 지원하지 않습니다(SELECT ... FOR UPDATE).

SQL Server에 해당하는 것은 SELECT 진술 힌트 UPDLOCK.

보다 SQL Server 온라인 설명서 자세한 내용은.

-최초의 생성 제출 (업데이트 시간) 마지막 업데이트 레코드 저장을 위해 제출 된 (업데이트 시간) -사용자가 레코드를 선택할 때 선택 시간 선택 시간과 업데이트 시간 필드를 비교합니다. if (업데이트 시간)> (선택 시간) 다른 사용자가 선택한 후이 레코드를 통해이 레코드를 업데이트하십시오. 기록

또 다른 옵션은 변경하려는 레코드의 값이 시작했을 때와 여전히 동일한지 테스트하는 것입니다.

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(customer_nm 필드를 표시하고 사용자가 이를 변경함)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

테이블에 새 열을 추가하고 최신 상태로 유지할 필요는 없지만 더 자세한 SQL 문을 만들고 통과해야 합니다. 새로운 그리고 오래된 필드를 저장 프로시저에 추가합니다.

또한 기록을 잠그지 않는다는 장점도 있습니다. 기록을 잠그지 말아야 할 때에도 잠긴 상태로 유지된다는 사실을 우리 모두 알고 있기 때문입니다.

데이터베이스가 이 작업을 수행합니다."선택..."을 보세요.for update"는 이런 종류의 작업을 위해 설계된 것입니다.선택한 행에 대한 쓰기 잠금을 제공하며 이를 커밋하거나 롤백할 수 있습니다.

나에게 있어서 가장 좋은 방법은 lastupdate 열(timetamp 데이터 유형)을 갖는 것입니다.선택 및 업데이트를 비교하면이 값을 비교할 때이 솔루션의 또 다른 발전은이 열을 사용하여 시간 데이터가 변경되는 시간을 추적 할 수 있다는 것입니다.업데이트 확인을 위해 isLock과 같은 컬럼을 그냥 생성하는 것은 좋지 않다고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top