트랜잭션과 무결성
트랜잭션과 무결성¶
참고: https://papimon.tistory.com/89
트랜잭션¶
- 일관성 있고 신뢰할 수 있는 방식으로 독립적이게 처리되는 "작업 단위"
- 예상치 못한 에러가 발생해도 데이터베이스를 신뢰성있는 상태로 만들 수 있도록 하는 "작업 단위"
- 데이터베이스의 변화를 나타냄
- All or Nothing
- Commit: 변경된 내용이 모두 영구적으로 저장되는 것
- Rollback: 트랜잭션으로 처리한 하나의 묶음 과정을 일어나기 전으로 돌리는 일
- ACID
- Atomicity - 원자성
- 트랜잭션 내의 모든 연산은 완벽하게 수행될 것
- 어느 하나가 오류나면 전체 취소될 것
- 모두 반영되기(Commit) or 전혀 반영되지 않기(Rollback)
- Consistency - 일관성
- 트랜잭션은 "허용된 규칙" 안에서만 데이터를 변경할 수 있음
- 허용된 규칙: PK/FK, Cascade, 트리거 등
- 트랜잭션은 "허용된 규칙" 안에서만 데이터를 변경할 수 있음
- Isolation - 독립성
- 트랜잭션 수행 시 다른 트랜잭션의 연산 작업이 중간에 끼어들지 못하도록 방지하는 것
- Durability - 지속성
- 성공적으로 완료된 트랜잭션은 시스템이 고장나더라도 영구적으로 반영될 것
- Atomicity - 원자성
- ACID를 고려하여 트랜잭션 범위 정하기
- Atomicity: 하나의 로직 내에서 변화가 필요한 모든 연산은 하나의 트랜잭션으로!
- Consistency: 데이터베이스에서 정의한 규칙 준수
- Isolation: 해당 작업 어느 수준까지 독립시킬 것인지 결정
- Durability: 트랜잭션의 기록을 SSD/HDD에 저장하는 것 (이건 벤더가 알아서)
스프링에서의 트랜잭션¶
@Transactional: 선언적 트랜잭션 with AOP- 핵심 비즈니스 로직 안 건드리면서 트랜잭션 사용가능
트랜잭션 전파 설정¶
- 진행 중인 트랜잭션에서 다른 트랜잭션 호출 시, 어찌 처리할건지!
- [REQUIRED(default)]
- 부모 트랜잭션 있다면 거기에 합류
- 부모 트랜잭션 없다면 새로운 트랜잭션 생성
- 하나의 트랜잭션으로 묶이기에 롤백 시 모든 진행 상황 롤백됨
- [REQUIRES_NEW]
- 무조건 새로운 트랜잭션 생성!
- 각각 트랜잭션 롤백되더라도 영향 없음
- [MANDATORY]
- 부모 트랜잭션에 합류
- 부모 트랜잭션 없다면 예외 발생
- [NESTED]
- 부모 트랜잭션 존재시 중첩 트랜잭션 생성
- 부모 트랜잭션 없다면 새로운 트랜잭션 생성
- 중첩된 트랜잭션 내부에서 롤백 시, 중첩 트랜잭션 시작까지만 롤백
- 중첩 트랜잭션은 부모 트랜잭션 커밋 시 같이 커밋!
- [NEVER]
- 트랜잭션 생성 안 함
- 부모 트랜잭션 존재 시 예외 발생
- [SUPPORTS]
- 부모 트랜잭션 있다면 합류
- 부모 트랜잭션 없다면 트랜잭션 생성 X
- [NOT_SUPPORTED]
- 부모 트랜잭션 있다면 보류
- 부모 트랜잭션 없다면 트랜잭션 생성 x
- [REQUIRED(default)]
트랜잭션 고립 수준¶
- 동시에 여러 트랜잭션 처리될 때, 트랜잭션끼리 얼마나 고립되어 있는지
- [DEFAULT(default)]
- DB 벤더사의 고립 수준 정책 따름
- Oracle: READ_COMMITTED
- MySQL: REPEATABLE_READ
- [READ_UNCOMMITTED]
- 트랜잭션 1이 커밋하지 않은 데이터에 대해, 트랜잭션 2가 읽는 것을 허용 => 잘 안써 너무 빡세 문제들이
- [READ_COMMITTED]
- 트랜잭션 1이 커밋한 데이터에 대해, 트랜잭션 2가 읽는 것을 허용
- [REPEATABLE_READ]
- 트랜잭션 1이 읽은 데이터에 대해 트랜잭션 1이 종료될 때 까지, 다른 트랜잭션에서 수정/삭제 허용 X
- 데이터 삽입은 가능
- 트랜잭션 1이 읽은 데이터에 대해 트랜잭션 1이 종료될 때 까지, 다른 트랜잭션에서 수정/삭제 허용 X
- [SERIALIZABLE]
- 트랜잭션 1이 읽은 데이터에 대해 트랜잭션 1이 종료될 때 까지, 다른 트랜잭션에서 수정/삭제/삽입 허용 X
- [DEFAULT(default)]
- 문제점
- [READ_UNCOMMITTED] - 동시성 MAX | 격리성 MIN
- 팬텀 리드
- 반복 가능하지 않은 조회
- 더티 리드
- 한 트랜잭션이 실행 중일 때 다른 트랜잭션에 의해 수정되었지만 커밋 되기도 전에 읽어버림
- [READ_COMMITTED]
- 팬텀 리드
- 반복 가능하지 않은 조회: 한 트랜잭션 내의 같은 행에 두 번 이상의 조회 발생했는데, 그 값이 다른 경우
- 트랜잭션 A에서 보석 100개 가지고 있다고 조회
- 트랜잭션 B에서 보석 1개 가지고 있다고 변경
- 트랜잭션 A에서 보석 1개 가지고 있다고 조회
- [REPEATABLE_READ] --- MySQL
- 팬텀 리드: 한 트랜잭션 내에서 동일한 쿼리 보냈을 때 조회 결과가 다른 경우
- Repeatable-read는 트랜잭션1에서 읽은 데이터에 대해 트랜잭션2가 삽입할 수 있게 허용하잖아?
- 그러다 보니까 트랜잭션2 나오기 전에 읽었던 데이터 != 트랜잭션 2 발생후 데이터가 될 수 있다는 것이지
- 다른 행이 선택될 수도 있다~
- [SERIALIZABLE] - 동시성 MIN | 격리성 MAX
- [READ_UNCOMMITTED] - 동시성 MAX | 격리성 MIN