데이터베이스 쿼리를 묶어주는 작업의 단위
서비스에서 가장 큰 문제는 => 데이터의 오염이다.
// 데이터의 신뢰가 깨지기 때문에
차라리 전체 다 실패하고, 다시 시도하는 게 안전하다.
그러기 위해서는 하나로 묶는 transaction가정이 필요함!!
ACID
는 Transaction을 정의하는 4가지 속성을 가리키는 약어 입니다.
A(Atomicity)
: 원자성 → 안전성 보장을 위해 가져야 할 성질 중의 하나로 트랜잭션과 관련된 작업들이 부분적으로 실행되다가 중단되지 않는 것을 보장하는 능력.C(Consistency)
: 일관성 → 트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 것.I(Isolation)
: 격리성 → 트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것.D(Durability)
: 지속성 → 성공적으로 수행된 트랜잭션에 대한 로그가 남아야하는 성질로 런타임 오류나 시스템 오류가 발생하더라도, 해당 기록은 영구적이어야 하는 것.
1단계 Read-Uncommitted 확정되지 않은 것을 읽어라
2단계 Read-committed 확정된것을 읽어라
3단계 repeatable-Read
4단계 Serializable(직렬화) 하나하나 일직선 상에 세워두고 차례대로 처리 => 속도는 낮지만, 가장 안전하다.
성능이란? 동시성이 높다!
성능이 느려지는 것은 동시성을 낮추고 안정성을 올리는 것!
결제테이블에서 철수의 결제내역 5000원을 조회 했는데 나중에 보니까 결제내역이 사라져있다?
5000원이 조회될 상태에는 아직 commit이 안된상태여서 읽혔지만 결국 commit이 없어 롤백 되니까 읽을 수 없게 되는 것이다.
판매 금액을 조회하여 세금을 뺴고, 다시 판매금액을 조회하여 수수료를 뺐는데..., DB가 이상해서 조회 할때마다 판매 금액이 바뀌네?
동시간 대에 동일한 쿼리를 날렸지만, 조회된 결과가 다르게 나온다는 뜻이다.
똑같은 쿼리를 조회할 떄마다 없던 데이터가 생기네..?
mysql은 Repeatable-Read이지만 유령읽기를 해결해서 보여준다.
성능을 위해서 오류가 발생하면 그때 롤벡하자고만 생각하고 락을 안건다.
어떻게든 막기위해 락을 건다.
select~for update 명시적 락
하나를 취소하거나 롤벡을 하지 않으면 두 API가 제대로 실행되지 않게 된다.
그러기에 예방을 해야하기 때문에 테이블 접근순서를 같게 제어해주는게 제일 좋다.
조인하면 => 조인된 테이블의 ROW에만 LOCK이 걸린다. 전테 테이블에 락이 걸리는 것이 아니다.
락을 건 적도 없는 데드락이 걸렸어 Repeatable-Read여도
명시적으로 락을 하지 않아도 업데이트(수정)할 때 락이 걸린다.
조회할때 명시적 락 걸기: select - for update
업데이트는 그냥 자동으로 row-lock걸림 => 업데이트한것이 락이 걸리지 않으면 처리 도중에 다른 곳에서 조회하고 그 row를 수정하면 안되기 때문이다!!
- 트랜잭션과 정전
서버가 재시작되면 자동으로 롤백이 된다.
- 커밋을 안했어도 롤백을 해야하는 이유
는 락을 걸었으면 해제해야하고 기록된 내용들도 삭제해야 디스크 용량을 확보할 수 있기 때문에