DB에서 하나의 논리적 기능을 수행하기 위한 작업의 단위
즉, 여러개의 쿼리의 묶음 단위이다.
트랜잭션은 원자성, 일관성, 독립성, 지속성이 있고 한번에 ACID 특징이라고 한다.
all or nothing
트랜잭션은 내부 쿼리가 모두 성공적으로 수행됬다면 성공, 하나라도 실패하면 실패다.
이걸 커밋과 롤백이라고 하는데, 컷밋은 여러 쿼리가 성공적으로 처리되었다고 확정하는 명령어다. 즉, "커밋 수행"은 "하나의 트랜잭션이 성공했다."로 볼 수 있는 것이다.
롤백은 트랜잭션 내부 쿼리가 하나라도 실패하는 순간, 커밋 시작 전으로 상태를 되돌리는 것이다.
커밋과 롤백 던분에 데이터의 무결성이 보장되며, 데이터 변경 전 변경 사항을 쉽게 확인할 수 있고, 해당 작업을 그룹화할 수 있다.
그런데 트랜잭션은 커넥션(데이터베이스와 트랙잭션의 연결) 단위로 수행하기 때문에 커넥션 객체를 넘겨서 트랜잭션을 수행한다.
매번 넘기는게 번거로워서 여러 트랜잭션 관련 메소드의 호출을 하나의 트랜잭션에 묶이도록 하는것이 트랜잭션 전파다.
@Transaction(readOnly = true)
public class MembetService{~~}
Spring에서는 이렇게 어노테이션을 통해서 여러 쿼리 관련 코드를 하나의 트랜잭션으로 처리한다.
허용된 방식으로만 데이터를 변경할 수 있따.
DB내부 데이터는 여러 조건과 규칙에 따라 유효함을 가져야한다.
예를 들면 내가 소지한 돈이 만원인데 친구한테 10만원을 빌려주는것. 현실적으로 불가능하다. 즉, 이 방식은 수행되지 못한다.
트랜잭션 수행 시 서로 끼어들지 못한다.
여러 트랜잭션은 서로 격리되어 마치 순차적으로 실행되는 것처럼 작동되어야 한다.
SERIALIZABLE -> REPEATABLE_READ -> READ_COMMITTED -> READ_UNCOMMITTED 순으로 동시성이 강해지면서 격리성이 낮아진다.
말 그대로 트랜잭션의 순차 진행이다. 여러 트랜잭션이 동시에 같은 행에 접근할 수 없다.
SERIALIZABLE에선 팬텀 리드 현상이 존재한다.
팬텀 리드는 한 트랜잭션 내부에서 동일한 쿼리를 보냈을 때 해당 조회 결과가 다른 경우를 말한다.
즉 A의 쿼리로 3개의 테이블이 조회 되고, B가 다른 레코드를 삽입, 그 후 A의 쿼리를 동일하게 입력했을때 4개의 테이블이 조회되는 현상이다.
하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없도록 막아주지만, 새로운 행을 추가하는건 허용한다.
REPEATABLE_READ에선 반복 불가능한 조회현상이 존재한다.
한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 서로 다른 값이 조회되는 경우다.
팬텀 리드와의 차이점은 반복 불가능한 조회는 행 값이 달라질 수 있는데, 팬텀 리드는 다른 행이 선택되는 것이다.
가장 많이 사용되는 격리 수준이며, 우리가 사용하는 DBMS의 기본값이다. 커밋이 완료된 데이터만 조회를 허용한다.
READ_COMMITTED에선 더티 리드 현상이 존재한다.
더티 리드는 반복 불가능한 조회와 유사하며, 한 트랜잭션이 실행 중일 때 다른 트랜잭션에 의해 수정되었지만 아직 커밋되지 않는 행의 데이터를 읽을 수 있을 때 발생한다.
즉, A가 어떤 값을 100 -> 1로 수정하고 아직 커밋되지 않았는데, B가 조회를 하자 1로 출력되는 경우
가장 낮은 격리 수준으로, 하나의 트랜잭션이 커밋되기 이전에 다른 트랜잭션에 노출되는 문제가 있다.
성공적으로 수행된 트랜잭션은 영구 적용된다.
즉, DB에 오류 발생시 원래 상태로 복구되는 기능이 있어야한다는 것이고,
체크섬, 저널링, 롤백등이 그 복구기능이다.
데이터의 정확성, 일관성, 유효성을 유지한다.
무결성이 유지되어야 DB에 저장된 데이터 값과 그 값에 해당하는 현실 세계의 실제 값이 일치하는 지에 대한 신뢰가 생긴다.
기본키로 선택된 필드는 NULL을 허용하지 않는다.
서로 참조 관계에 있는 두 테이블의 데이터는 항상 일관된 값을 유지해야한다.
특정 속성에 대해 고유한 값을 갖도록 조건이 주어진 경우, 그 속성 값은 모두 고유한 값을 갖는다.
특정 속성 값에 NULL이 올 수 없다는 조건이 주어진 경우 그 속성 값은 NULL이 될 수 없다.