SELECT… FOR UPDATE를 언제 사용합니까?
의 사용 사례를 이해하도록 도와주세요 SELECT ... FOR UPDATE.
질문 1 : 다음은 언제 SELECT ... FOR UPDATE사용해야하는지에 대한 좋은 예 입니까?
주어진:
- 방 [id]
- 태그 [ID, 이름]
- room_tags [room_id, tag_id]
- room_id 및 tag_id는 외래 키입니다.
애플리케이션은 모든 룸과 해당 태그를 나열하려고하지만 태그가없는 룸과 제거 된 룸을 구분해야합니다. SELECT ... FOR UPDATE를 사용하지 않으면 다음과 같은 일이 발생할 수 있습니다.
- 처음에는 :
- 방 포함
[id = 1] - 태그에는
[id = 1, name = 'cats'] - room_tags 포함
[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.tag_id = 1 AND tags.id = room_tags.tag_id;- 빈 목록을 반환
이제 스레드 1은 방 1에 태그가 없다고 생각하지만 실제로 방은 제거되었습니다. 이 문제를 해결하려면 스레드 1이이어야합니다. 그러면 스레드 1이 완료 될 때까지 스레드 SELECT id FROM rooms FOR UPDATE2가 삭제되지 rooms않습니다. 그 맞습니까?
질문 2 : 언제 하나를 사용해야 SERIALIZABLE트랜잭션 격리가 대 READ_COMMITTED와 SELECT ... FOR UPDATE?
답변은 이식 가능해야합니다 (데이터베이스에 한정되지 않음). 가능하지 않은 경우 이유를 설명해주세요.
룸과 태그 간의 일관성을 유지하고 룸이 삭제 된 후 반환되지 않도록하는 유일한 이동식 방법은로 잠그는 것입니다 SELECT FOR UPDATE.
그러나 일부 시스템에서 잠금은 동시성 제어의 부작용이며 FOR UPDATE명시 적으로 지정하지 않고도 동일한 결과를 얻을 수 있습니다.
이 문제를 해결하려면 스레드 1이이어야합니다. 그러면 스레드 1이 완료 될 때까지 스레드
SELECT id FROM rooms FOR UPDATE2가 삭제되지rooms않습니다. 그 맞습니까?
이것은 데이터베이스 시스템이 사용하는 동시성 제어에 따라 다릅니다.
MyISAMinMySQL(및 기타 여러 오래된 시스템)은 쿼리 기간 동안 전체 테이블을 잠급니다.에서
SQL Server,SELECT쿼리, 그들은 검사 한 기록 / 페이지 / 테이블에 대한 공유 잠금을 게재 할 동안DML(이후 독점적으로 승진 또는 공유 잠금으로 강등된다) 쿼리 장소 업데이트 잠금. 배타적 잠금은 공유 잠금과 호환되지 않으므로SELECT또는DELETE쿼리는 다른 세션이 커밋 될 때까지 잠 깁니다.사용하는 데이터베이스
MVCC(예Oracle:PostgreSQL,,MySQLwithInnoDB)에서DML쿼리는 레코드의 복사본을 생성하며 (하나 또는 다른 방식으로) 일반적으로 독자는 작성자를 차단하지 않으며 그 반대의 경우도 마찬가지입니다. 이러한 데이터베이스의 경우 aSELECT FOR UPDATE가 편리합니다. 마찬가지로 다른 세션이 커밋 될 때까지SELECT또는DELETE쿼리를 잠급니다SQL Server.
때 하나를 사용해야
REPEATABLE_READ대 트랜잭션 격리를READ_COMMITTED가진SELECT ... FOR UPDATE?
일반적으로 REPEATABLE READ가상 행 (수정되지 않고 다른 트랜잭션에서 나타나거나 사라진 행)을 금지하지 않습니다.
년
Oracle및 이전PostgreSQL버전,REPEATABLE READ실제로 동의어입니다SERIALIZABLE. 기본적으로 이것은 트랜잭션이 시작된 후 변경된 내용을 볼 수 없음을 의미합니다. 따라서이 설정에서 마지막Thread 1쿼리는 방이 삭제 된 적이없는 것처럼 반환합니다 (원하는 것일 수도 있고 아닐 수도 있음). 삭제 한 후 방을 표시하지 않으려면 행을 잠 가야합니다.SELECT FOR UPDATE에서
InnoDB,REPEATABLE READ그리고SERIALIZABLE다른 사항은 다음과 같습니다 독자SERIALIZABLE효과적으로 동시 방지들이 평가 기록에 대한 모드 설정 다음 키 잠금,DML그들에이. 따라서SELECT FOR UPDATE직렬화 가능 모드는 필요하지 않지만REPEATABLE READ또는READ COMMITED.
격리 모드에 대한 표준은 쿼리에서 특정 단점을 보지 않도록 규정하지만 방법 (잠금 사용 또는 사용)은 정의하지 않습니다 MVCC.
내가 "필요하지 않다"고 말할 때 " SELECT FOR UPDATE특정 데이터베이스 엔진 구현의 부작용 때문에"추가 했어야했습니다.
짧은 답변 :
Q1 : 예.
Q2 : 어떤 것을 사용하든 상관 없습니다.
긴 대답 :
select ... for update의미하는대로 A 는 특정 행을 선택하지만 현재 트랜잭션에 의해 이미 업데이트 된 것처럼 (또는 ID 업데이트가 수행 된 것처럼) 잠급니다. 이를 통해 현재 트랜잭션에서 다시 업데이트 한 다음 커밋 할 수 있습니다. 다른 트랜잭션이 이러한 행을 어떤 방식 으로든 수정할 수 없습니다.
Another way of looking at it, it is as if the following two statements are executed atomically:
select * from my_table where my_condition;
update my_table set my_column = my_column where my_condition;
Since the rows affected by my_condition are locked, no other transaction can modify them in any way, and hence, transaction isolation level makes no difference here.
Note also that transaction isolation level is independent of locking: setting a different isolation level doesn't allow you to get around locking and update rows in a different transaction that are locked by your transaction.
What transaction isolation levels do guarantee (at different levels) is the consistency of data while transactions are in progress.
참고URL : https://stackoverflow.com/questions/10935850/when-to-use-select-for-update
'Programing' 카테고리의 다른 글
| 실제 세계에서 함수형 프로그래밍을 어떻게 사용할 수 있습니까? (0) | 2020.08.17 |
|---|---|
| Tmux 대 iTerm2 분할 창 (0) | 2020.08.17 |
| 강력한 이름의 어셈블리를 사용하는 이유는 무엇입니까? (0) | 2020.08.17 |
| 새 서비스를위한 기본 TCP / IP 포트를 어떻게 선택해야합니까? (0) | 2020.08.17 |
| 커밋 메시지는 현재 또는 과거 시제로 작성해야합니까? (0) | 2020.08.17 |