데이터베이스발행일 2024. 7. 4.원본 https://blog.naver.com/jword_/223501395823 ↗

데이터베이스 트랜잭션 관리

데이터베이스 트랜잭션 관리 — #데이터베이스트랜잭션 #트랜잭션ACID #트랜잭션 #transaction #transactionACID #트랜잭션커밋 #...

#DataBase#Naver Blog

#데이터베이스트랜잭션 #트랜잭션ACID #트랜잭션 #transaction #transactionACID #트랜잭션커밋 #트랜잭션부분커밋 #transactioncommit #transactionPartiallyCommit #개발자의도구들

🚨📝 📖 📒💡

​

AI스쿨 msa기반 java 백엔드 코스 중에 공부한 내용을 작성하였습니다

\* 현재 Spring 프로젝트를 진행 중입니다. 전체적인 목차를 보시려면 여기를 눌러주세요.

데이터 베이스 트랜잭션

OS를 공부해보신 분들이라면 thread에 대해서 들어보셨을 것 같은데요. 특히나 웹서버 같은 다중 클라이언트 환경에서 thread를 적절히 처리하는 것이 중요함을 잘 알고 계시리라 생각됩니다.

​

​

데이터베이스도 마찬가지입니다. 여러 사용자가 동시에 하나의 DB에 접근하기 때문에 동시성 문제를 반드시 고려해야 해요. 이 문제를 해결하기 위해 데이터베이스는 transaction이라는 개념을 사용합니다. Transaction은 하나의 논리적 작업 단위로, 여러 연산을 묶어서 "모두 성공하거나, 모두 실패하거나" 둘 중 하나를 보장합니다.

트랜잭션이란?

앞서 말했듯이 트랜잭션은 데이터베이스에서 처리되는 일련의 작업 단위를 의미합니다. 트랜잭션은 데이터베이스의 무결성과 일관성을 유지하는 데 핵심적인 역할을 하기 때문에 반드시 잘 관리해야 합니다. 트랜잭션 관리에 실패하면 데이터가 중복 저장되거나, 일부만 반영되어 불완전한 상태로 남거나, 심하면 데이터가 손실될 수도 있습니다.

트랜잭션 동작 단계

데이터베이스 내에서 트랜잭션은 여러가지 단계를 가지게 됩니다. 앞서 트랜잭션이 일련의 데이터베이스에서 수행되는 일련의 작업 단위라고 했는데요. 트랜잭션이 생성되었다고 해서 무작정 바로 실행하고 반영해버린다면, 데이터 베이스의 일관성이 깨져버릴 수 잇습니다. 그래서 트랜잭션이 안정하게 완료되기까지의 과정을 여러 단계로 나누어 관리합니다.

​

  1. Activie States
  2. Partially committed
  3. Committed
  4. Failed
  5. Terminated state

​

각 단계별로 뚜렷한 목적이 존재하니 해당 단계가 왜 필요한지에 대해 이해를 하면서 공부하시면 좋을 것 같습니다.

​

1. Active States

트랜잭션이 처음으로 실행된 상태로, 현재 트랜잭션이 실행중임을 의미합니다.

​

2. Partially commited

트랜잭션이 반영되어 데이터의 수정이 일어난 상태입니다. 하지만, 아직까지는 데이터 베이스에 commit되지 않았고, 메모리상에서만 변경이 이루어진 상태입니다.

​

3. Committed

모든 변경사항이 디스크에 영구적으로 반영된 상태입니다. 이 단계부터는 rollback이 불가능합니다.

​

4. Failed

Active 또는 Partially Committed 상태에서 오류가 발생하거나 트랜잭션이 중단되면 Failed 상태로 진입합니다.

​

5. Aborted

Failed 상태 이후, 트랜잭션이 수행한 모든 변경 사항이 rollback되어 원래 상태로 복구된 상태입니다.

​

5. Terminated State

Committed 또는 Aborted 이후, 트랜잭션의 생명주기가 완전히 종료된 상태입니다.

이미지

출처: fauna

https://fauna.com/blog/database-transaction

트랜잭션 ACID

마지막으로 앞서 언급한 transaction ACID에 대한 설명은 따로 정리해둔 글이 있기 때문에 간단하게 정리하고 넘어가고자 합니다.

​

(여기서는 state 관점에서 보시면 더 이해가 잘되어요\*)관계형 데이터 베이스에서 지켜야하는 트랜잭션의 특징인데, 시험에도 자주 나오니 공부하시면 좋을 것 같습니다.

​

🚨Atomacity : all or nothing 트랜잭션이 완전히 comiited가 되거나, 아니면 완전히 이 상태로 roll back 해야한다는 원칙​🚨Consistency 트랜잭션의 핵심 이점은 바로 Consistenct입니다. 트랜잭션은 오직 데이터 베이스 엔진에게 권한을 부여받을 때문 데이터에 영향을 줄 수 있습니다.​🚨Isolation 동시에 다중 트랜잭션들이 실행될 수 있습니다. 하지만, 모든 트랜잭션은 각 개별적으로 독립성을 유지해야하며, 다른 트랜잭션에 어떠한 영향도 줘서는 안됩니다.​🚨Durability 트랜잭션이 성공적으로 commit된 이후, 트랜잭션 자체가 영구적으로 살아있어야 한다는 의미 -> 이를 구현하기 위해 log를 남긴다.

트랜잭션과 관련된 문제들

트랜잭션 동시성 문제

여러 트랜잭션이 동시에 같은 데이터에 접근하면 다양한 문제가 발생합니다.

​

  1. Dirty Read: 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 문제입니다. 만약 해당 트랜잭션이 Rollback 되면, 읽은 데이터는 존재하지 않는 값이 됩니다.

​

  1. Non-Repeatable Read: 같은 트랜잭션 내에서 동일한 데이터를 두 번 조회했는데, 그 사이에 다른 트랜잭션이 수정하여 결과가 달라지는 문제입니다.

​

  1. Phantom Read: 같은 조건으로 여러 행을 조회했는데, 그 사이에 다른 트랜잭션이 행을 추가했거나 삭제하여 결과 집합이 달라지는 문제입니다.

​

  1. Lost Update: 두 트랜잭션이 동시에 같은 데이터를 수정할 때, 한쪽의 변경 사항이 덮어씌워져 사라지는 문제입니다.

​

해결방법

​

1. Isolation Level(격리 수준)

격리 수준은 동시에 실행되는 트랜잭션들이 서로 얼마나 영향을 주고 받는지를 정의한 것 입니다. 격리 수준이 낮을수록 동시성은 좋으나, 정합성이 떨어집니다. 높은 경우 정합성은 좋으나 성능은 떨어집니다. 이 트레이드 오프를 이해하면서 격리 수준에 따른 장,단점을 비교하면 공부하면 좋습니다.

​

Read Uncommitted

가장 낮은 격리 수준입니다. 말 그대로 커밋되지 않은 데이터도 읽을 수 있는 수준입니다.

​

다른 트랜잭션이 아지 커밋하지 않는 변경사항을 읽기 때문에 Dirty Read가 발생할 수 있습니다. 아직 커밋되지 않는 데이터가 Rollback 되면 존재하지 않는 값을 읽어 사용할 수 있습니다.

​

Read Commited

커밋된 데이터만 읽을 수 있습니다. 대부분의 RDBMS에서 기본값으로 설정되어 있습니다. Oracle, PostgreSQL 등이 이 수준을 기본으로 사용합니다.

​

커밋된 데이터만 읽기 때문에 Dirty Read가 발생하지 않습니다. 하지만, 같은 트랜잭션 내에서 같은 데이터를 두번 조회할 때, 그 사이에 다른 트랜잭션이 커밋해 버리면 결과가 달라질 수 있습니다. Non-Repeatable Read 및 Phantom Read가 발생할 수 있습니다.

​

Repeatable Read

같은 트랜잭션 내에서는 동일한 데이터를 여러 번 읽어도 항상 같은 값을 조장하는 수준입니다. MySQL(InnoDB)에서 기본값으로 사용하고 있습니다.

​

트랜잭션이 시작된 시점의 스냅샷을 기준으로 데이터를 읽기 때문에, 다른 트랜잭션이 중간에 값을 수정하고 커밋하더라도 영향을 받지 않습니다. Dirty Read, Non-Repeatable Read가 해결 됩니다.

​

하지만 여전히 Phantom Read가 발생할 수 있습니다. 다른 트랜잭션이 새로운 행을 추가하면 조회 결과의 행 개수가 달라질 수 있습니다. 다만, MySQL의 InnoDB에서는 Next-Key Lock을 사용해서 Phantom Read까지 어느 정도 방지합니다.

​

Serializable

가장 높은 격리 수준입니다. 트랜잭션들이 마치 순차적으로 실행되는 것처럼 동작하게 만드는 수준이지요.

​

모든 읽기 작업에도 락을 걸기 때문에 Dirty Read, Non-Repeatable Read, Phantom Read가 모두 해결됩니다. 데이터 정합성은 완벽하게 보장되지요.

​

하지만 그만큼 동시성이 크게 떨어지고, 데드락 발생 가능성도 높아집니다. 성능 저하가 심하기 때문에 정말 엄격한 정합성이 필요한 금융 거래 같은 특수한 상황에서만 사용하는 것이 일반적입니다.

​

2. Locking

  • Shared Lock (공유 락): 읽기 작업 시 사용, 여러 트랜잭션이 동시에 읽을 수 있지만, 쓰기는 불가.
  • Exclusive Lock(베타 락): 쓰기 작업 시 사용, 해당 트랜잭션만 접근 가능

​

3. MVCC(Multi-Version Concurrency Control)

데이터를 수정할 때 기존 데이터를 덮어쓰지 않고 새로운 버전을 생성합니다. 각 트랜잭션은 자신의 시점에 맞는 버전을 읽기 때문에 딱 없이도 동시성을 확보할 수 있습니다. MySQL(InnoDB), PostgreSQL 등에서 사용합니다.

​

4. Optimistic vs Pessimistic Locking

  • Pessimistic Locking: 충돌이 발생할 것이라 가정하고, 데이터 접근 시 미리 락을 건다.
  • Optimistic Locking: 충돌이 드물다고 가정하고, 커밋 시점에 버전을 비교하여 중돌을 감지한다.

​

​