IT

SELECT ... FOR UPDATE를 사용할 때?

itgroup 2022. 12. 7. 22:23
반응형

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이 완료될 때까지.그것이 맞습니까?

이는 데이터베이스 시스템에서 사용 중인 동시성 제어에 따라 달라집니다.

  • MyISAMMySQL(및 기타 몇 가지 오래된 시스템)은 쿼리 기간 동안 테이블 전체를 잠급니다.

  • SQL Server,SELECT쿼리는 검사한 레코드/페이지/테이블에 공유 잠금을 배치합니다.DMLquery는 업데이트 잠금(나중에 배타적 잠금으로 승격되거나 공유 잠금으로 강등됨)을 배치합니다.배타적 잠금은 공유 잠금과 호환되지 않으므로 다음 중 하나 또는SELECT또는DELETE쿼리는 다른 세션이 커밋될 때까지 잠깁니다.

  • 를 사용하는 데이터베이스MVCC(마치Oracle,PostgreSQL,MySQL와 함께InnoDB), a.DMLquery는 레코드의 복사본을 작성합니다(어떤 방법으로든).일반적으로 리더는 라이터를 차단하지 않으며 그 반대도 마찬가지입니다.이러한 데이터베이스의 경우SELECT FOR UPDATE것 : () : (SELECT ★★★DELETE커밋될 합니다.SQL Server

하면 좋을까요?REPEATABLE_READ vs "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

반응형