programing

SQL Server에서 Oracle의 "SELECT FOR UPDATE WAIT"와 유사한 방법으로 단일 행을 잠그려면 어떻게 해야 합니까?

bestprogram 2023. 3. 13. 21:09

SQL Server에서 Oracle의 "SELECT FOR UPDATE WAIT"와 유사한 방법으로 단일 행을 잠그려면 어떻게 해야 합니까?

Oracle 데이터베이스에 연결하여 작업을 수행하는 프로그램이 있습니다.SQL Server 데이터베이스도 지원하도록 프로그램을 조정하고 싶습니다.

Oracle 버전에서는 "SELECT FOR UPDATE WAIT"를 사용하여 필요한 특정 행을 잠급니다.SELECT 결과에 따라 업데이트가 이루어지고 다른 세션이 동시에 수정되지 않을 수 있는 상황에서 먼저 수동으로 잠궈야 합니다.시스템은 동일한 데이터에 동시에 액세스하려고 하는 세션의 영향을 받기 쉽습니다.

예를 들어 다음과 같습니다.
두 명의 사용자가 가장 높은 우선순위로 데이터베이스 내의 행을 가져오려고 시도하고, 해당 행을 사용 중으로 마크하고, 해당 행에 대한 작업을 수행한 후 나중에 사용할 수 있도록 다시 마킹합니다.오라클

BEGIN TRANSACTION;
SELECT ITEM_ID FROM TABLE_ITEM WHERE ITEM_PRIORITY > 10 AND ITEM_CATEGORY = 'CT1'
    ITEM_STATUS = 'available' AND ROWNUM = 1 FOR UPDATE WAIT 5;
UPDATE [locked item_id] SET ITEM_STATUS = 'unavailable';
COMMIT TRANSACTION;

쿼리는 내 코드로 동적으로 작성됩니다.또한 이전에 가장 선호하는 행이 사용 불가능으로 표시되어 있으면 두 번째 사용자가 자동으로 다음 행으로 이동합니다.게다가, 다른 카테고리에서 작업하는 다른 유저는, 서로의 잠금이 해제되는 것을 기다릴 필요가 없습니다.최악의 경우 5초 후에 오류가 반환되고 작업이 취소됩니다.

마지막으로 어떻게 하면 SQL Server에서도 동일한 결과를 얻을 수 있을까요?이론상으로는 효과가 있을 것 같은 힌트를 찾고 있었습니다.그러나 다른 잠금을 방지하는 유일한 잠금 장치는 "UPDLOCK"과 "XLOCK"뿐이며, 둘 다 테이블 레벨에서만 작동합니다.
행 레벨에서 동작하는 이러한 잠금 힌트는 모두 공유 잠금이며, 이 또한 나의 요구를 만족시키지 못합니다(두 사용자 모두 같은 행을 동시에 잠글 수 있으며, 둘 다 사용할 수 없는 것으로 표시하고 해당 항목에 대해 다중 작업을 수행할 수 있습니다).

일부 사용자는 세션이 수정한 사람이 시간 수정자인지 확인할 수 있도록 "시간 수정자" 열을 추가하는 것처럼 보이지만, 이 경우 많은 수의 중복 액세스와 불필요한 액세스가 발생할 수 있습니다.

찾고 거예요.with (updlock, holdlock) ★★★★★★★★★★★★★★★★★★★★★ ★select을 잡다.exclusive잠금(업데이트에 필요),shared잠근다.holdlock힌트는 트랜잭션이 종료될 때까지 잠금을 유지하도록 SQL Server에 지시합니다.

FROM TABLE_ITEM with (updlock, holdlock)

설명서에 기재된 바와 같이:

XLOCK

트랜잭션이 완료될 때까지 배타적 잠금을 수행하고 유지하도록 지정합니다.ROWLOCK, PAGLOCK 또는 TAB과 함께 지정된 경우LOCK, 배타적 잠금은 적절한 세분화 수준에 적용됩니다.

솔루션에서는WITH(XLOCK, ROWLOCK):

BEGIN TRANSACTION;

SELECT ITEM_ID
FROM TABLE_ITEM
WITH(XLOCK, ROWLOCK)
WHERE ITEM_PRIORITY > 10 AND ITEM_CATEGORY = 'CT1' AND ITEM_STATUS = 'available' AND ROWNUM = 1;

UPDATE [locked item_id] SET ITEM_STATUS = 'unavailable';

COMMIT TRANSACTION;

SQL Server에는 잠금 힌트가 있지만 사용자가 제공한 Oracle 예시와 같은 문장은 포함되지 않습니다.SQL 서버에서 이를 수행하려면 실행할 문이 포함된 트랜잭션에 격리 수준을 설정합니다. MSDN 페이지를 참조해 주세요만, 일반적인 구조는 다음과 같습니다.

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRANSACTION;

    select * from ...

    update ...

COMMIT TRANSACTION;

Serializable은 가장 높은 분리 수준입니다.그 외의 옵션에 대해서는, 링크를 참조해 주세요.MSDN에서:

시리얼 가능 다음을 지정합니다.

문은 수정되었지만 다른 트랜잭션에 의해 아직 커밋되지 않은 데이터를 읽을 수 없습니다.

현재 트랜잭션이 완료될 때까지 다른 트랜잭션은 현재 트랜잭션에서 읽은 데이터를 수정할 수 없습니다.

다른 트랜잭션에서는 현재 트랜잭션이 완료될 때까지 현재 트랜잭션의 문에서 읽은 키 범위에 해당하는 키 값을 가진 새 행을 삽입할 수 없습니다.

WITH(ROWLOCK)사용해 보셨습니까?

BEGIN TRAN

   UPDATE your_table WITH (ROWLOCK)
   SET your_field = a_value
   WHERE <a predicate>

COMMIT TRAN

언급URL : https://stackoverflow.com/questions/9502273/in-sql-server-how-can-i-lock-a-single-row-in-a-way-similar-to-oracles-select