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쿼리는 검사한 레코드/페이지/테이블에 공유 잠금을 배치합니다.DMLquery는 업데이트 잠금(나중에 배타적 잠금으로 승격되거나 공유 잠금으로 강등됨)을 배치합니다.배타적 잠금은 공유 잠금과 호환되지 않으므로 다음 중 하나 또는SELECT또는DELETE쿼리는 다른 세션이 커밋될 때까지 잠깁니다.를 사용하는 데이터베이스
MVCC(마치Oracle,PostgreSQL,MySQL와 함께InnoDB), a.DMLquery는 레코드의 복사본을 작성합니다(어떤 방법으로든).일반적으로 리더는 라이터를 차단하지 않으며 그 반대도 마찬가지입니다.이러한 데이터베이스의 경우SELECT FOR UPDATE것 : () : (SELECT★★★DELETE커밋될 합니다.SQL Server
하면 좋을까요?
REPEATABLE_READvs "transaction isolationREAD_COMMITTEDSELECT ... 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 |