티스토리 뷰
Transaction
- 여러 읽기/쓰기를 논리적으로 하나로 묶음
- 트랜잭션 시작 -> 여러 쿼리 실행 -> 커밋 or 롤백
- 모두 반영(커밋) or 모두 반영 안 하기(롤백)
- 트랜잭션 범위는 컨넥션 기준
- 트랜잭션의 모든 쿼리는 같은 커넥션에 있어야 한다.
- 커넥션이 3개라면 트랜잭션을 가질 수 있다
- 트랜잭션 전파
- 여러 메서드 호출이 한 트랜잭션에 묶이도록 하기 위해 필요
- 스프링 프레임워크: 메서드 간에 커넥션 객체를 전달하지 않아도 한 트랜잭션으로 묶어서 실행
- 여러 메서드 호출이 한 트랜잭션에 묶이도록 하기 위해 필요
- 외부 연동 주의
- 한 트랜잭션에 외부 API 연동이 있을 때 롤백 처리에 주의해야 한다.
경쟁 상태(Race Condition)
여러 트랜잭션이 동시에 같은 레코드에 접근하면 동시성 문제(경쟁 조건) 발생
- 해결책
- 트랜잭션을 순서대로 실행
- 동시성에 대한 문제 원천 차단
- 한 번에 한 개의 트랜잭션만 처리하기 때문에 성능(처리량) 저하
- 트랜잭션 격리(Isolation)
- 트랜잭션을 순서대로 실행
Dirty Read(커밋되지 않은 데이터 읽기)
- 어떤 트랜잭션이 커밋 되지 않은 다른 트랜잭션(혹은 aborted 된)이 쓴 데이터를 읽는 것을 일컫는다
- A 계좌에서 B 계좌로 100만 원을 송금시킨다고 했을 때 송금 과정 중에 계좌 잔고 조회를 하면 1000이어야 할 금액이 900으로 조회가 될 수 있다.
Dirty Write(커밋되지 않은 데이터 덮어쓰기)
- 어떤 트랜잭션이 커밋되지 않은 다른 트랜잭션(혹은 aborted 된)의 트랜잭션 데이터를 overwrite 하는 것을 일컫는다
- 방을 빌리는 과정에서 room name과 participant를 변경해준다.
- Ranyinudo는 room name=Appraisal, participant=Ranyinudo로 변경한다.
- 동시에 Ginika는 room name=1-1, participant=Ginika로 변경한다.
- Ginika, Ranyinudo의 트랜잭션이 아래 그림과 같이 실행되면서 되면서 room name=1-1, participant=Ranyinudo의 결과를 갖게 된다.
Read Skew(읽는 동안 데이터 변경)
- 보통 시간 차이로 발생하는 이상 현상
- Repeatable Read에서 생길 수 있는 현상
- Dirty Read가 아닌 정상 프로세스로 커밋된 결과로 인해 오래된 버전과 새로운 버전의 데이터를 모두 만나게 되는 경우
- 2번 계좌에서 1번 계좌로 송금 트랜잭션이 있을 때
- Alice가 해당 트랜잭션 전에 1번 계좌에서 500을 확인
- Alice가 해당 트랜잭션 후에 2번 계좌를 확인했을 때 400을 확인하게 되면 100이 사라진 거처럼 느낄 수 있다.
Lost Update(갱신 손실)
- read-modify-write 주기로 작업할 때 발생
- 동시 쓰기 작업 시 발생하는 쓰기 충돌 중 하나
- i.e. count증가, 위키 페이지 수정
- 종종 이와 같은 충돌을 "Last Write Wins"로 해결하기도 한다.
해결책
- 원자적(atomic) 연산
- DB가 지원하는 원자적 연산 사용
- 동시 수정 요청에 대해 DB가 순차 처리
- i.e. UPDATE counters SET value = value + 1 WHERE key = 'foo';
- DB가 지원하는 원자적 연산 사용
- 명시적 잠금(exciplit lock)
- 조회할 때 수정할 행을 미리 잠금
- i.e. select ... for update
- 조회할 때 수정할 행을 미리 잠금
- CAS(Compare And Set)
- 각 Row에다가 Version 붙이고, UPDATE 시마다 Version 이 변경하지 않았을 때만 진행하고 그 외에는 재시도
- Repeatable Read 쓸 때 유의
Write Skew
- Lost Update문제의 일반화된 문제다
- concurrent 한 트랜잭션이 같은 객체를 읽고 다른 객체를 업데이트하는 것
- 같은 객체를 업데이트하면 Lost Update 문제, 다른 객체를 업데이트하면 Write Skew 문제라 할 수 있다.
- 우버와 같은 서비스에서 Omphile가 가능한 차를 호출(broadcast) 한다.
- Driver A와 Driver B는 customer가 배차가 안된 거를 확인하고 각각 둘 다 배차를 하게 되는 문제다
- 다른 예시로는 당직 트랜잭션이 있다.
- 트랜잭션이 처음 시작할 때는 2명이었는데 트랜잭션 종료 후 0명이 된다.
- 당직 수를 1명으로 유지해야 하는 정책이 깨질 수 있는 버그다.
Phantom
- 한 트랜잭션이 다른 트랜잭션의 검색 결과를 바꿔버리는 문제
해결책
- 빈 결과를 SELECT 한 후에 INSERT를 하는 경우에는 아무것도 잠글 것이 없으므로, 스냅숏 격리로는 안되고 직렬성 격리가 필요
트랜잭션 격리(Transaction Isolation)
트랜잭션을 서로 격리해서 다른 트랜잭션이 영향을 주지 못하게 함
격리 수준(Isolation Level)
Isolation Level/Read phenomena | Dirty Reads | Lost Updates | Non-repeatable Reads | Phantoms |
Read Uncommitted | o | o | o | o |
Read Committed | x | o | o | o |
Repeatable Read | x | x | x | o |
Serializable | x | x | x | x |
Read uncommitted
- SELECT 질의 수행 시 해당 데이터에 Shared Lock이 걸리지 않는다.
- Dirty Read는 있지만 Drity Write는 없다.
Read Committed
- 대부분의 DBMS에서 사용하는 레벨(MySQL 제외)
- SELECT 질의 수행시 해당 데이터에 Shared Lock이 걸린다.
- 커밋된 데이터만 읽기 (Dirty Read 방지)
- 커밋된 값과 트랜잭션 진행 중인 값을 따로 보관
- 커밋된 데이터만 덮어쓰기 (Dirty Write 방지)
- 행 단위 잠금 사용
- 같은 데이터를 수정한 트랜잭션이 끝날 때까지 대기
- 행 단위 잠금 사용
Repeatable Read/Snapshot Isolation
- 트랜잭션 동안 같은 데이터를 읽게 함
- i.e. MVCC(Multi-Version Concurrency Control)
- 읽는 시점에 특정 버전에 해당하는 데이터만 읽음
- i.e. MVCC(Multi-Version Concurrency Control)
Serializable
- 트랜잭션이 완료될 때까지 다른 사용자는 그 영역에 해당되는 데이터에 대한 수정 및 입력이 불가능
- 인덱스 잠금이나 조건 기반 잠금 등 사용
ACID
Atomic/Atomicity(원자성)
- 트랜잭션에 기록한 모든 내용이 성공하거나 모두 취소되는 것을 보장
Consistency(일관성)
- 데이터가 Correct State 라면 트랜잭션을 수행하고 난 Correct State여야 한다. 1
- 데이터가 항상 진실인 불변식(invariant)을 만족한다는 보장
- Application 정책과 관련, ACID 중 유일한 Application의 책임
- i.e. 회계 프로그램에서 차변과 대변이 항상 같아야 하는 정책
Isolated(격리성)
- 동시에 실행되는 트랜잭션은 서로 격리된다는 보장
- 트랜잭션은 다른 트랜잭션을 방해할 수 없다.
Durable(지속성)
- 데이터베이스가 죽어도 데이터가 손실되지 않는다는 보장
- 트랜잭션이 커밋됐다면 시스템에 남아있어야 한다.
Reference
- 프로그래밍 초식 : DB 트랜잭션 조금 이해하기 01
- https://ketanbhatt.com/db-concurrency-defects/
- https://youngminz.netlify.app/posts/data-intensive-application-transaction
- https://nominationp.github.io/2020/03/22/transcations-week-isolation-levels/
- https://dotnettutorials.net/lesson/phantom-read-concurrency-problem-sql-server/
- 도메인의 유효 범위, 무결성 제약조건 등의 제약 조건을 위배하지 않는 정상적인 상태 [본문으로]
반응형
'CS' 카테고리의 다른 글
[Network] HTTP/0.9 ~ 1.1 (0) | 2022.01.03 |
---|---|
[Network/OS] Network Socket(IP Socket, WebSocket) (0) | 2021.12.27 |
Interpreter VS Compiler (0) | 2021.11.26 |
[Network]기본 개념 (0) | 2021.10.30 |
[Network]Cloud 종류 (0) | 2021.10.25 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- gitignore
- docker-compose
- 위코드
- http
- Isolate level
- no-op
- Python
- QUIC
- Complier
- user-agent
- buildkit
- thetextbook
- cka
- 프리온보딩
- HTTP/2
- GitHub
- 원티드
- 창업
- pytest
- 덕타이핑
- Git
- Network
- go
- database
- direnv
- inflearn
- MSA
- k8s
- HTTP/3
- web_server
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함