SELECT ... FOR UPDATE를 사용할 때?
이면에 있는 사용 사례를 이해하는데 도움을 주세요.SELECT ... FOR UPDATE
.
질문 1: 다음 예시는 다음과 같은 경우에 적합한가?SELECT ... FOR UPDATE
사용해야 합니까?
지정:
- 방[아이디]
- 태그[ID, 이름]
- room_buff[room_id, tag_id]
- room_id 및 tag_id는 외부 키입니다.
응용 프로그램에서는 모든 객실과 해당 태그를 나열하려고 하지만 태그가 없는 객실과 제거된 방을 구분해야 합니다.SELECT ... FOR UPDATE를 사용하지 않을 경우 다음과 같이 됩니다.
- 처음에:
- 방에는 다음이 포함됩니다.
[id = 1]
- 태그에는 다음이 포함됩니다.
[id = 1, name = 'cats']
- room_filen에는 다음이 포함됩니다.
[room_id = 1, tag_id = 1]
- 방에는 다음이 포함됩니다.
- 스레드 1:
SELECT id FROM rooms;
returns [id = 1]
- 스레드 2:
DELETE FROM room_tags WHERE room_id = 1;
- 스레드 2:
DELETE FROM rooms WHERE id = 1;
- 스레드 2: [트랜잭션 커밋]
- 스레드 1:
SELECT tags.name FROM room_tags, tags WHERE room_tags.room_id = 1 AND tags.id = room_tags.tag_id;
- 빈 목록을 반환합니다.
스레드 1은 룸 1에 태그가 없다고 생각하지만 실제로는 룸이 삭제되어 있습니다.이 문제를 해결하려면 스레드1은SELECT id FROM rooms FOR UPDATE
따라서 스레드2가 에서 삭제되는 것을 방지합니다.rooms
스레드 1이 완료될 때까지.그것이 맞습니까?
질문 2: 언제 사용해야 합니까?SERIALIZABLE
트랜잭션 격리 대READ_COMMITTED
와 함께SELECT ... FOR UPDATE
?
답변은 (데이터베이스 고유의 것이 아니라) 이식 가능해야 합니다.그게 안 되면 이유를 설명해 주세요.
객실과 태그 간의 일관성을 확보하고 삭제 후 객실이 반환되지 않도록 하는 유일한 휴대용 방법은 다음과 같이 잠그는 것입니다.SELECT FOR UPDATE
.
단, 일부 시스템에서는 잠금이 동시성 제어의 부작용으로 인해 다음과 같은 결과를 얻을 수 있습니다.FOR UPDATE
명쾌하게
이 문제를 해결하려면 스레드1은
SELECT id FROM rooms FOR UPDATE
따라서 스레드2가 에서 삭제되는 것을 방지합니다.rooms
스레드 1이 완료될 때까지.그것이 맞습니까?
이는 데이터베이스 시스템에서 사용 중인 동시성 제어에 따라 달라집니다.
MyISAM
에MySQL
(및 기타 몇 가지 오래된 시스템)은 쿼리 기간 동안 테이블 전체를 잠급니다.인
SQL Server
,SELECT
쿼리는 검사한 레코드/페이지/테이블에 공유 잠금을 배치합니다.DML
query는 업데이트 잠금(나중에 배타적 잠금으로 승격되거나 공유 잠금으로 강등됨)을 배치합니다.배타적 잠금은 공유 잠금과 호환되지 않으므로 다음 중 하나 또는SELECT
또는DELETE
쿼리는 다른 세션이 커밋될 때까지 잠깁니다.를 사용하는 데이터베이스
MVCC
(마치Oracle
,PostgreSQL
,MySQL
와 함께InnoDB
), a.DML
query는 레코드의 복사본을 작성합니다(어떤 방법으로든).일반적으로 리더는 라이터를 차단하지 않으며 그 반대도 마찬가지입니다.이러한 데이터베이스의 경우SELECT FOR UPDATE
것 : () : (SELECT
★★★DELETE
커밋될 합니다.SQL Server
하면 좋을까요?
REPEATABLE_READ
vs "transaction isolationREAD_COMMITTED
SELECT ... FOR UPDATE
「일부러」REPEATABLE READ
에서는 팬텀 행행)을 .
»
Oracle
그 이전의 「」PostgreSQL
버전,REPEATABLE READ
실제로와 동의어이다SERIALIZABLE
기본적으로는 트랜잭션이 시작된 후 변경된 내용을 볼 수 없습니다.이 " " "가" 입니다.Thread 1
쿼리는 회의실을 삭제하지 않은 것처럼 반환합니다(원하는 회의실인지 아닌지는 상관없습니다.에 자물쇠를 .SELECT FOR UPDATE
»
InnoDB
,REPEATABLE READ
★★★★★★★★★★★★★★★★★」SERIALIZABLE
것:독자:독자SERIALIZABLE
평가된 레코드에 대해 next-key locks)를 설정하여 동시 next-key locks(다음 키 잠금)를 효과적으로 합니다.DML
그 위에 올려놔요.래서 so so so는 없어요.SELECT FOR UPDATE
모드에서는 할 수 있지만 serializable 모드에서는 사용할 수 .REPEATABLE READ
★★★★★★★★★★★★★★★★★」READ COMMITED
.
위드)은되어 있지 .MVCC
( ) ) ) 。
가 '라고 하면 '필요없어'라고 하면SELECT FOR UPDATE
"저는 "특정 데이터베이스 엔진 구현의 부작용 때문에"라고 덧붙였어야 했습니다.
단답:
Q1: 네.
Q2: 어떤 것을 사용하든 상관없습니다.
장황한 답변:
A select ... for update
특정 행을 선택할 뿐만 아니라 현재 트랜잭션에 의해 이미 갱신된 것처럼(또는 ID 갱신이 수행된 것처럼) 잠글 수도 있습니다.이렇게 하면 현재 트랜잭션에서 해당 행을 다시 업데이트한 후 커밋할 수 있으며, 다른 트랜잭션은 이러한 행을 수정할 수 없습니다.
다른 관점에서 보면 다음 두 개의 문이 원자적으로 실행되는 것과 같습니다.
select * from my_table where my_condition;
update my_table set my_column = my_column where my_condition;
의 을 받는 my_condition
잠긴 상태이므로 다른 트랜잭션에서는 수정할 수 없습니다.따라서 트랜잭션 분리 수준에는 차이가 없습니다.
또한 트랜잭션 분리 수준은 잠금과 독립적입니다. 분리 수준을 다르게 설정하면 트랜잭션에 의해 잠긴 다른 트랜잭션의 행을 잠그거나 업데이트할 수 없습니다.
트랜잭션 격리 수준이 보장하는 것은 트랜잭션 진행 중 데이터의 일관성입니다.
언급URL : https://stackoverflow.com/questions/10935850/when-to-use-select-for-update
'IT' 카테고리의 다른 글
사전 병합 방법 (0) | 2022.12.07 |
---|---|
Java - JPA - @Version 주석 (0) | 2022.12.07 |
LoDash: 객체 속성 배열에서 값 배열 가져오기 (0) | 2022.12.07 |
숫자가 정확성을 잃지 않고 도달할 수 있는 JavaScript의 최대 정수 값은 얼마입니까? (0) | 2022.12.07 |
Java로 "time above"를 알려주세요. (0) | 2022.12.07 |