ex)
라이언이 어피치에게 2000원을 송금했다.
- 트랜잭션 시작
- {라이언 잔액} -> InnoDB undo log에 저장
- {어피치 잔액} -> InnoDB undo log에 저장
- ( update {라이언 잔액} = {라이언 잔액} - 2000 ) -> DB에 적용
- ( update {어피치 잔액} = {어피치 잔액} + 2000 ) -> DB에 적용
transaction commit
※undo log는 바로 delete 되지 않음else)
- 트랜잭션 시작
- {라이언 잔액} -> InnoDB undo log에 저장
- {어피치 잔액} -> InnoDB undo log에 저장
- ( update {라이언 잔액} = {라이언 잔액} - 2000 ) -> DB에 적용
error 발생transaction rollback
-> InnoDB undo log에 저장되어 있는 데이터로 데이터베이스 덮어쓰기
ex)
제약조건으로 Consistency를 유지 - > unique , foreign key
ex)
트랜잭션은 서로 간섭하지 않고 독립적으로 동작
-> 많은 성능을 포기해야하므로 개발자가 제어 가능
-> 트랜잭션 격리레벨을 통해 제어
ex)
데이터베이스 성능에 핵심은 Random I/O의 양
Update, Insert와 같은 쓰기 작업이 일어날 때 마다 디스크에 데이터를 밀어 넣는 것은 성능에 안좋은 영향을 줌그래서 메모리에 데이터 작업을 먼저 실행한다
-> 메모리는 휘발성을 가져 데이터가 유실되면...?
-> WAL(write ahead logging)로 어느정도 해소
WAL
ex)
transaction1 == 라이언이 어피치에게 2000원을 보내는 상황
transaction2 == 조회를 하는 상황라이언의 잔액 3000원 , 어피치의 잔액 100원
transaction1 - 1. select id, priceAcount from member where id="라이언" and id="어피치"; id = 라이언, priceAcount = 3000, id = 라이언, priceAcount = 100
transaction1 - 2. update member set priceAcount = priceAcount - 2000 where id="라이언"; update member set priceAcount = priceAcount + 2000 where id="어피치";
3. transaction1 - 트랜잭션에 오류가 발생 rollback;
4. transaction2 - 어피치가 조회한 상황 select id, priceAcount from member where id="어피치";
transaction2 어피치가 가져온 정보는 어피치의 잔액 2100원
※ 어피치의 잔액이 2100원이고 롤백되기 전에 데이터를 가져온 상황
ex)
transaction1 == 라이언이 잔액 조회를 3번 실행
transaction2 == 어피치가 라이언에게 500원을 송금라이언의 잔액 3000원
transaction1 - 1. select id, priceAcount from member where id="라이언"; id = 라이언, priceAcount = 3000
transaction1 - 2. select id, priceAcount from member where id="라이언"; id = 라이언, priceAcount = 3000
transaction2 - 3. update member set priceAcount = priceAcount + 500 where id="라이언"; commit;
transaction1 - 4. select id, priceAcount from member where id="라이언"; id = 라이언, priceAcount = 3500
transaction1이 가져온 정보는 라이언의 잔액 3500원
※ 라이언의 잔액이 한번에 트랜잭션 내에서 결과값이 다름
ex)
transaction1 == 잔액이 1000원 이상인 사람들을 조회
transaction2 == 잔액 100원이 있던 어피치의 계좌에 2000원이 입금라이언의 잔액 3000원
transaction1 - 1. select id, priceAcount from member where priceAcount >= 1000; id = 라이언, priceAcount = 3000
transaction2 - 2. update member set priceAcount = priceAcount + 2000 where id="어피치"; commit;
transaction1 - 3. select id, priceAcount from member where id="라이언"; id = 라이언, priceAcount = 3000 , id = 어피치, priceAcount = 2100
transaction1이 가져온 정보는 라이언만 조회되어야 하는데 어피치까지 포함하여 결과값이 변경
Read Uncommitted : 3가지 격리수준을 모두 허용 (거의 안씀)
Read Committed : Dirty Read만 허용 X (가장 많이 씀)
Repeatable Read : Phantom Read만 허용
(많이 쓰이지만 deadLock 이슈 때문에 Read Committed보다 적게 쓰임)
Serializable Read : 모두 허용 X (거의 안씀)
출처 및 링크 : fastcampus