Skip to content

Latest commit

 

History

History
106 lines (57 loc) · 5.58 KB

Commit&Rollback.md

File metadata and controls

106 lines (57 loc) · 5.58 KB

1. What is transaction Processing?

데이터베이스의 상태를 바꾸는 기능을 수행하기 위한 작업의 단위

2. What is Commit and Rollback in a database?

Commit

  • 작성한 쿼리문에서 Update, Delete, Insert를 수행했을 때, 그 쿼리문 수행결과를 확정

Rollback

  • commit 이전에 수행
  • 쿼리문 수행결과에 대해 번복을 함. 즉, 쿼리문 수행 이전으로 원상복구

3. Why do we need transactions?

  • A라는 사람이 B에게 100,000원을 송금한다고 생각해보자.

A 계좌에서는 100,000원 이 출금이 될것이고, B 계좌에는 100,000원 이 입금이 될것이다.

만약, 입금하는 도중에 여러 작업들이 동시에 이루어진다면 어떻게 될까?

A 계좌에서 출금이 성공
B의 계좌에 입금하는 도중 오류 발생한다면? 철A 계좌에서는 이미 천원이 줄었으나, B 받은 돈이 없는 상황이 발생한다.  

특히 금융권에서는 더욱더 이러한 일이 절대 발생하면 안된다는 생각을 하게 될것이다.

이때, 우리는 트랜잭션의 중요성을 깨닫게된다.

A 계좌에서 출금, B 계좌에 입금 하는 기능을 하나의 트랜잭션으로 관리해야 한다.

  • 왜 트랜잭션으로 관리해야할까?

하나의 트랜잭션으로 관리하면, B 계좌에 입금하는 기능이 실패했을 경우, A 계좌에 돈이 다시 입금이 이루어진다. 이때, A계좌에 돈이 다시 입금이 이루어지는 과정을 Rollback 이라고 한다.

만약, 이러한 오류가 발생하지 않고 정상적으로 A의 계좌에서 출금이 되고 B의 계좌에서 입금이 정상적으로 되었다면 이것의 개념을 Commit 이라고 한다.

What if many transactions are competing?

여러개의 트랜잭션이 경쟁을 하게 된다면 우리는 여러개의 트랜잭션이 동시에 실행되는 상황을 고려해야한다.

특정 트랜잭션이 수정 후 아직 커밋을 하지 않았는데, 다른 트랜잭션이 그 레코드에 접근할 수도 있다. 이러한 경우에 발생 할 수 있는 상황은 3가지이다.

Dirty Read

트랜잭션 A가 어떤 값을 1에서 2로 변경하였고, 아직 커밋하지 않은 상황에서 트랜잭션B가 같은 값을 읽는다면 트랜잭션 B는 2를 읽을 것이다. 이 때 A가 롤백된다면 트랜잭션B는 잘못된 값을 읽은 것이 된다.

아직 수정 중인 데이터에 접근을 허용할 경우 발생하는 데이터 불일치

Non-Repeatable Read

트랜잭션 A가 값 1을 읽은 이후 A는 같은 쿼리를 실행할 예정이면, 그 사이에 트랜잭션 B가 값 1을 2로 바꾸고 커밋하게 되면서 A는 같은 쿼리 두번을 날렸으나, 두 쿼리의 결과가 다르게 되는 문제가 발생한다.

한 트랜잭션에서 같은 쿼리를 두번 실행했을 때 발생하는 데이터 불일치이다. 앞서 설명한 Dirty Read에 비해서는 발생 확률이 좀 적은데 하나의 트랜잭션에서 두개를 수행해야된다는 전제 조건이 깔리게 된다.

Phantom Read

트랜잭션 A가 어떤 조건을 사용하여 특정 범위의 값들 [0,2,4,6,8]을 읽었다. 이후 A는 같은 쿼리를 실행할 예정인데, 그 사이에 트랜잭션 B가 같은 테이블에 값[1,3,5]을 추가하고 커밋을 수행한다면 A는 같은 쿼리를 다시 실행했지만 두번째 결과는 [1,2,3,4,5,6,8]을 얻는다.

한 트랜잭션에서 일정 범위의 레코드를 두번 이상 읽을 때 발생하는 데이터 불일치이다. 앞서 설명한 문제점들 보다 발생 확률이 가장 적다.

How to resolve transaction confliction problems?

트랜잭션 격리수준

트랜잭션 격리 수준은 총 4가지이다. 수준(Level)이 높을수록 성능은 떨어지므로, 높은 격리 수준을 채택하는 것이 항상 좋은 방법은 아니다. 적절한 수준을 채택하는 것이 좋다.

Level0 - Read Uncommited

다른 트랜잭션이 커밋하지 않은 레코드에 접근이 가능하다. 가장 낮은 수준의 트랜잭션 격리이다. 그래서 앞서 언급한 3가지 문제가 모두 발생한다. 그러나 성능은 가장 뛰어나다.

Level1 - Read Commited

항상 커밋된 레코드만 읽는다. 그러므로 아직 커밋되지 않는 레코드를 읽다가 발생하는 Dirty Read는 방지된다. 하지만 나머지 두가지 문제는 예방할 수 없다. 대부분의 DBMS에서 기본적으로 채택하고 있는 방식으로 알려져 있다.

Level2 - Repeatable Read

특정 트랜잭션이 읽은 레코드에 대하여 그 트랜잭션이 끝날 때까지 다른 트랜잭션이 수정/삭제하는 것을 방지한다. 한 트랜잭션에서 같은 쿼리를 두번 실행했을 때 결과가 다른 문제인 Non-Repeatable-Read가 예방된다. 하지만 특정 범위를 지정한 것도 아니고, 레코드 생성을 방지한 것은 아니므로 Phantom Read는 예방할 수 없다. Oracle에서 종종 사용하는 SELECT ... FOR UPDATE 구문이 이 방식이다.

Level3 - Serializable Read

어떤 트랜잭션이 여러개의 레코드를 조회할 때, 그 트랜잭션이 끝날 때까지 조회 범위에 새로운 레코드를 조회/생성/수정/삭제 하는 것을 방지한다. 모든 동시성 관련 문제를 예방할 수 있으나, 성능이 가장 안좋다.

Reference

https://preamtree.tistory.com/154

https://it-sungwoo.tistory.com/57

https://trustall.tistory.com/36