하지만 여러 SQL문을 Transactin 처리하고 싶다면 AutoCommit를 disable하고 사용해야된다
Mysql로 예를 들면
START TRANSACTION; // 해당 구문을 통해 AutoCommit 속성이 자동으로 disable
UPDATE member SET name = "Lee" WHERE id = 1;
UPDATE member SET name = "Kim" WHERE id = 2;
COMMIT; // COMMIT / ROLLBACK 에서 transaction이 종료되면 자동으로 enable
1) Transaction 시작 SQL (AutoCommit 속성 disable)
2) 로직 수행
3.1) 문제 없다면 COMMIT를 통해 데이터 반영
3.2) 문제가 발생했다면 ROLLBACK를 통해 이전 상태로 되돌림
4) Transaction 종료 시 (AutoCommit 속성 enable)
트랜잭션은 여러 트랜잭션이 동시에 실행되어도 마치 각각 격리되어 다른 트랜잭션의 영향을 받지않고 동작하는 isolation 속성을 보장해야된다
이를 보장하기 위해 serializablity와 recoverablility를 제공한다
트랜잭션은 스레드와 같이 동시에 접근하면 동시성 이슈가 발생할 수 있다
이를 lost update라고 하는데 밑에 사진을 보면

재고가 12가 남아있었고 모두 합쳐서 5개가 팔렸다. 그러면 총 재고가 7개가 남아야한다.
하지만 동시에 접근하게 되면서 데이터를 읽은 시점의 차이가 발생하여 stock의 update가 잘못된 경우이다.
성능적인 측면에서 한번에 하나의 트랜잭션만 실행되기 때문에 좋은 성능은 기대할 수 없지만 정확한 결과가 나온다.
성능적인 측면에서 한번에 여러 트랜잭션을 실행하기 때문에 많은 트랜잭션을 처리할 수 있다.
즉, 성능적인 측면에서 좋지만 lost update와 같은 이상한 결과가 나올 수 있습니다.
이를 해결하고자 나온 개념이 Conflict 개념입니다
아래 3가지 조건이 부합하면 Conflict라고 한다
1. 서로 다른 trasaction
2. 같은 데이터 접근
3. 최소 하나의 transaction은 write
위 사진을 보면 2번의 read-write conflict와 1번의 write-write conflict가 발생하였다.
이 conflict 연산은 순서가 바뀌면 결과도 바뀝니다
두 조건을 모두 만족하면 conflict equivalent
1. 두 schedule은 같은 transaction을 가진다
2. 어떤 confliting 연산 순서도 양쪽 schedule 모두 동일하다
위 사진에서 각각의 Conflict의 연산 순서가 전부 동일하다면 같은 Schedule로 보는 것입니다.
이처럼 Serail schedule하고 Conflict equivalent 상태일 때 Conflict serializable이라고 합니다.
그러면 오른쪽도 Noneserial schedule이지만 Conflict serializable합니다.
K의 계좌에서 H로 20만원 이체하는 T1, H가 20만원 입금하는 T2가 동시에 발생하였다고 가정
t1 ==================
read(K_balance = 100)
write(K_balance = 80)
t2-------------------
read(H_balance = 100)
write(H_balance = 120)
t1====================
read(H_balace = 120) // t2의 write(H_balance = 120)에 의존성이 있다
write(H_balance = 140)
======================
t2 commit
---------------------
t1 commit
t1 ==================
read(K_balance = 100)
write(K_balance = 80)
t2-------------------
read(H_balance = 100)
write(H_balance = 120)
t2 commit // t2 종료 에러가 발생해도 해당 t2만 롤백하면 된다
t1====================
read(H_balace = 120)
write(H_balance = 140)
t1 commit
t1 ==================
read(K_balance = 100)
write(K_balance = 80)
read(H_balace = 120)
write(H_balance = 140)
t1 commit
t2-------------------
read(H_balance = 100)
write(H_balance = 120)
t2 commit
| Isolation level | Dirty read | Non-repeatable read | Phantom read |
|---|---|---|---|
| Read uncommitted | O | O | O |
| Read committed | X | O | O |
| Repeatable read | X | X | O |
| Serializable | X | X | X |
concurrency control를 어떻게 구현할 지 정의해놓은 isolation level
특징
트랜잭션 내부에서 또 다른 트랜잭션을 진행할 때 어떻게 할지 결정하는 기법이다
https://easy-code-yo.tistory.com/26
https://mangkyu.tistory.com/269