트랜잭션 이해
트랜잭션이란
- DB에서 수행되는 일련의 작업들로 이뤄진,
- 하나의 논리적인 작업 단위이다.
- 작업 처리 중에 일어날 수 있는 오류나 사고 등으로 데이터가 예상하지 못한 상태가 되는 것을 방지하기 위함이다.
- 예를 들어, A의 통장에서 B의 통장으로 이체를 한다면
- A의 잔고에서 100원이 나갔다.
- B의 잔고에서 100원이 들어오려 할 때, 디비가 터져버렸다.
- 다시 복구를 시켰더니 A의 잔고에서는 100원이 분명히 사라졌는데,
- B의 잔고에는 100원이 들어오지 않았다.
- A의 잔고에서 100원이 나가는 과정과 B의 잔고에 100원이 들어오는 과정이 하나의 과정으로 묶어 사고를 방지할 수 있다.
- 여러 과정을 묶어 하나의 과정으로 만든 것이 트랜잭션이다.
트랜잭션의 사용
- 트랜잭션에는 두 가지 동작이 있다.
- commit
- 트랜잭션 내의 일련의 디비 조작 명령을 실행하고,
- 그 실행의 결과를 디비에 반영하는 것이다.
- rollback
- 트랜잭션 작업 수행의 결과를 저장하지 않고,
- 트랜잭션 시작 전의 상태로 되돌려 놓는 것이다.
- 조회야 뭐 상관없고, 변경이 반영되느냐 롤백되느냐 하는 것이다.
- A 세션의 트랜잭션에서 변경이 일어났고, 아직 커밋되지 않았다.
- 다른 세션인 B에서 A에서 변경이 일어난 데이터를 조회하면, A에 의한 변경은 보이지 않는다.
- 만약 세션 B에서 커밋되지 않은 A의 변경이 보인다면, 데이터 정합성 문제가 생긴다.
- 세션 A가 롤백을 해버린다면,
- B는 롤백이 된줄 모르고 변경된 데이터를 사용해버리면 정합성이 깨진다.
- commit
자동 커밋과 수동 커밋
- 자동 커밋
- 쿼리 한 줄마다 자동으로 커밋을 해주는 것이다.
- 편리하지만 트랜잭션 기능을 사용할 수 없다.
- 기본적으로 활성화되어 있다.
- 수동 커밋
- 작업이 끝나고 마지막에 커밋 또는 롤백을 해줘야하는 것.
- 커밋이나 롤백을 명시해주지 않으면 타임아웃 뒤에 그냥 롤백이 되어버린다.
- 수동 커밋으로 바꾸면 세션이 유지되는 동안에 수동 커밋도 유지된다.
ACID
- 트랜잭션이 갖춰야 하는 네 가지 속성을 의미한다.
- Atomicity
- 원자성
- 트랜잭션 내의 작업들은 전체가 하나의 작업으로,
- 누구는 성공하고, 누구는 실패했다는 개념이 없다.
- 전체가 성공했거나, 전체가 실패했다만 있다.
- Consistency
- 일관성
- 모든 트랜잭션은 일관성 있는 디비 상태를 유지해야 한다.
- 디비에서 정한 무결성 제약 조건을 잘 지켜야 한다.
- Isolation
- 고립성
- 여러 트랜잭션들이 수행될 때, 서로의 결과에 영향을 주지 않아야 한다.
- A 아이템을 a 트랜잭션이 잡고 작업을 수행할 때,
- b 트랜잭션도 A 아이템을 변경하는 작업을 수행한다면 기다린다던가 해야한다.
- Durability
- 지속성
- 트랜잭션이 커밋되면 항상 DB에 반영이 되어야 한다.
- 만약 시스템 오류나 어떤 사고로 트랜잭션이 디비에 반영되지 않았더라도,
- 로그를 확인하여 다시 작업하는 등의 복구를 해야한다.
고립성의 단계
- 고립성을 완벽히 지키기 위해서는 트랜잭션들을 하나하나 순차적으로 처리해야 한다.
- 이러면 성능적으로 너무 떨어지게 된다.
- 성능을 위해서 격리성을 지키지 않는다면,
- 여러 트랜잭션들에 의해 예상치 못한 결과가 디비에 들어가고 만다.
- 이러한 고립성을 ANSI에서 표준화하여 4단계로 나누었다.
- Read Uncommitted
- 어느 한 트랜잭션에서 어떤 데이터 A를 작업하고 있는 도중에, (아직 커밋이나 롤백되지 않은 상태)
- 다른 트랜잭션에서 A의 값을 읽을 수 있다.
Read Committed
- Repeatable Read
- Serializable
Isolation Level | Dirty Read | Non-repeatable Read | Phantom Read |
---|---|---|---|
Read Uncommitted | Possible | Possible | Possible |
Read Committed | Not Possible | Possible | Possible |
Repeatable Read | Not Possible | Not Possible | Possible |
Serializable | Not Possible | Not Possible | Not Possible |
- Dirty Read
- 다른 트랜잭션에 의해 변형이 일어난, 커밋은 되지 않은 데이터를 읽는 것을 말한다.
- Dirty Write
- 백수 아들의 통잔 잔고가 1000원이었다고 한다.
- 엄마가 아들의 잔고를 조회중이다.
- 거의 동시에 아빠도 아들의 잔고를 열어보았다.
- 엄마는 백수 아들이 안쓰러워 10000원을 입금해 주었다.
- 엄마의 세션에서 아들의 잔고가 11000원이 되었다.
- 아직 커밋은 하지 않았다.
- 아빠 역시 백수 아들이 안타까워 10000원을 입금해 주었다.
- 아빠의 세션에서 아들의 잔고가 11000원이 되었다.
- 아직 커밋은 하지 않았다.
- 엄마가 먼저 커밋을 했다.
- 아들의 잔고가 11000원으로 디비에 반영되었다.
- 아빠가 뒤따라서 커밋을 했다.
- 아들의 잔고가 11000원으로 디비에 반영되었다.
- 엄마 아빠가 각각 만원씩 입금을 해주셨지만, 안타깝게도 백수 아들은 만원만 받았다.
- 이것을 더티 쓰기라고 한다.
- Non-repeatable Read
- 한 트랜잭션 내에서 같은 쿼리를 수행했는데, 결과가 다르게 나오는 경우를 말한다.
- 예를 들어,
- A 트랜잭션에서 어떤 값을 조회해서 10이 나왔다.
- A 트랜잭션이 그 값에 10을 곱하면 100이 된다.
- 그 다음 B 트랜잭션이 같은 값에 10을 더해서 결과는 110이 된다.
- 그러나 Non-repeatable Read가 일어난다면,
- A 트랜잭션이 조회한 값이 10이 나왔다.
- A 트랜잭션이 그 값에 10을 곱하려고 할 때, B가 10을 더하고 커밋 해버렸다.
- 처음 조회한 값 10과 다른 값 20이 나와버렸다.
- A가 커밋되었을 때 그 값음 200이 되어버렸다.
- Phantom Read
- 한 트랜잭션에서 일정 범위의 레코드들을 두 번 이상 읽을 때,
- 처음에 없었던 레코드(유령 레코드)가 나오는 현상이다.
- 예를 들어,
- A 트랜잭션에서 봉천의 20대들을 조회했다.
- 여기서 100명이 조회되었다.
- 그때 B 트랜잭션이 봉천동에 20대 보근의 전입신고를 커밋했다.
- A 트랜잭션은 봉천의 20대들을 group by 성별로 count() 했다.
- 왜인지 남녀 합계가 101명이었다.
- A 트랜잭션에서 봉천의 20대들을 조회했다.
DB 락
- 위에서 발견한 여러가지 트랜잭션에서 일어나는 문제들을 해결하기 위해서
- 어느 한 트랜잭션이 어떤 레코드 A를 사용하는 동안에는 다른 트랜잭션이 레코드 A를 변경할 수 없게 잠구는 방법이다.
- 대신 락 time out이 있어서 그 시간이 지나면 자동으로 락이 풀린다.
- 그걸 락이라고 한다.
DB 락 - 변경
-
This post is licensed under CC BY 4.0 by the author.