일반적으로 두 가지 잠금 방법이 있습니다.
먼저 비관적 인 잠금 기능이 있습니다. 이 접근 방식에서는 다른 사람이 행을 변경하지 못하게하는 행 (SELECT ... FOR UPDATE
)을 잠급니다. 그런 다음 UPDATE
을 수행합니다. 변경 사항을 커밋하면 잠금이 해제됩니다. 이 경우 버전 번호/타임 스탬프 열 (적어도 잠금을 지원하지 않음)을 가질 필요가 없으며 코드가 비교적 쉽습니다.
비관적 잠금의 단점은 사용자가 잠재적으로 데이터를 편집하는 페이지에 앉아있을 때마다 잠금을 유지해야한다는 것입니다. HTTP가 상태없는 프로토콜이므로 웹 기반 응용 프로그램을 만드는 경우 기술적으로 매우 어렵습니다. 처음에 페이지를 렌더링하는 요청은 일반적으로 연결 풀에서 연결을 가져오고 SELECT
을 수행 한 다음 페이지가 완료되면 풀에 연결을 반환합니다. 데이터 갱신 요청은 일반적으로 다른 데이터베이스 세션과의 다른 연결에서 발생하므로 첫 번째 세션에서 행을 잠그고 두 번째 세션에서 행을 업데이트 할 수 없습니다. 비관적으로 행을 잠그고 싶다면 사용자가 데이터 편집을 마칠 때까지 하나의 데이터베이스 연결이 특정 중간 계층 세션에 연결되어 있는지 확인하려면 백엔드에서 많은 작업을 수행해야합니다. 이것은 일반적으로 확장성에 매우 부정적인 영향을 미치고 모든 종류의 세션 관리 문제를 야기합니다. 예를 들어, 페이지를 요청했는지, 행을 잠그고, 로그 아웃하거나 변경하지 않고 브라우저를 닫았는지 어떻게 알 수 있습니까? 얼마나 오랫동안 레코드를 데이터베이스에 잠겨 둘 것입니까? 다른 세션이 행을 잠그려고하면 어떻게됩니까? 첫 번째 사람이 점심을 먹으러 나간 경우 세션 잠금이 얼마나 오래 기다리게 할 것입니까? 일반적으로 세션 및 세션 상태를 관리하는 것은 너무 비현실적이므로 사람들은 웹 기반 응용 프로그램에서 비관적 잠금을 구현하지 않습니다.
두 번째 옵션은 낙관적 잠금입니다. 이 방법에서는 버전 번호/타임 스탬프를 행에 추가합니다. 데이터를 쿼리 할 때이 버전 번호/타임 스탬프를 선택합니다. 그런 다음 나중에 업데이트를 수행하고 실제로 수정 된 행 수를 확인할 때 WHERE
절에서이 값을 사용합니다. 정확히 한 행만 수정하면 행을 읽은 후에 행이 변경되지 않았 음을 알 수 있습니다. 0 행을 수정하면 행이 변경되어 오류를 처리 할 수 있음을 알 수 있습니다.
업데이트를 할 준비가되면 당신은
version
를 사용하는 경우, 당신은 같은 것을 할 것
SELECT address_line1, city, state, zip, version
FROM addressTable
WHERE address_id = `<<some key>>`
따라서, 예를 들어, 버전 번호와 함께 데이터를 선택할 것이다 당신의 UPDATE
및 행이
UPDATE addressTable
SET address_line1 = `<<new address line 1>>`,
city = `<<new city>>`,
state = `<<new state>>`,
zip = `<<new zip>>`,
version = version + 1
WHERE address_id = `<<some key>>`
AND version = `<<version you read initially>>`
IF(SQL%ROWCOUNT = 0)
THEN
-- Darn. The row must have changed since you read it. Do something to
-- alert the user. Most likely, the application will need to re-query the
-- data to see what the address has been changed to and then ask the user
-- whether they want to re-apply the changes.
RAISE_APPLICATION_ERROR(-20001, 'Oops, the row has changed since you read it.');
END;
다음 오류가있는 유용한 일을 할 것입니다 귀하의 응용 프로그램
를 변경 한 경우 오류가 발생. 일반적으로 이는 데이터를 다시 쿼리하고, 사용자에게 변경 사항을 제시하고, 변경 사항을 계속 적용할지 묻는 것과 같은 일을하는 것입니다. 예를 들어, 주소를 읽고 편집을 시작하고, 점심을 먹고, 동료가 로그인하고, 동일한 주소를 읽고, 수정하고, 저장 한 다음 되돌아 와서 변경 사항을 저장하려고하면 일반적으로 의미가 있습니다. 제 동료가 주소를 뭔가 새로운 것으로 바 꾸었습니다. 편집을 계속하고 싶습니다. 아니면 포기하고 싶습니다.
SELECT FOR UPDATE 그러나 이것은 낙관적 인 잠금이라고 생각하지 않습니다. – Vadim
오, 정말요? select for update에 대해 자세히 설명해 주시겠습니까? 나는 이것이 행을 고정 시켰다고 생각 했는가? – wonderBoy322
@ wonderBoy322 행을 잠그지 만 비관적 인 잠금을 고려할 것입니다. 그것은 "비관적"입니다. 누군가 다른 사람이 같은 줄을 수정하려고 할 때 당신이 그것을 사용하기 때문입니다. "낙관적 인"대 다른 사람이 같은 행을 수정할 것이라고 가정하면 모든 작업을 수행 한 다음 맨 끝에는 다른 사람이 아무 것도 변경하지 않았는지 확인하기 위해 일종의 플래그를 확인합니다. –