티스토리 뷰

DB

[DB] 락(Lock)과 트랜잭션

rimo (리모) 2024. 3. 9. 17:24

 

아래 글에 이어 작성되었습니다.

 

 

[DB] 트랜잭션(Transaction)과 트랜잭션 격리 수준(Isolation Level)

트랜잭션이란? 트랜잭션은 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미합니다. 데이터베이스

munak.tistory.com

 

락과 트랜잭션에 대하여


락(Lock)

 

트랜잭션을 구현하기 위해 대부분*의 데이터베이스 관리 시스템(DBMS)은 락을 사용합니다. 

 

락은 데이터베이스의 일관성과 무결성을 보장하기 위한 중요한 메커니즘 중 하나입니다.

데이터베이스의 SQL도 여타 다른 프로그래밍 언어와 같이 변수를 설정하고 명령어를 실행할 수 있습니다.

이때, 특정 변수에 대해서 다른 명령어들이 접근할 수 없게 잠금을 할 수 있는데 이를 락이라고 합니다.

 

만약 잠금이 없다면 여러 커넥션이 동시에 데이터를 수정하여 레코드의 값을 예측할 수 없는 상태로 만들 수 있겠죠.

 

 

MVCC*

락을 사용하지 않고 트랜잭션 동시성을 관리하는 DBMS들이 있습니다. PostgreSQL, Oracle가 그 예인데요.

이들은 락 대신 다중 버전 동시성 제어(Multi-Version Concurrency Control) 기술을 사용하여 트랜잭션의 일관성을 보장합니다.

 

간단히 설명하고 넘어가자면,

MVCC는 다른 트랜잭션이 데이터를 읽을 때 해당 데이터의 스냅샷(snapshot)을 생성하여 사용하는 방법입니다.
스냅샷 데이터에 대한 변경은 커밋이 될 때까지 다른 데이터베이스 사용자에게는 보이지 않습니다.

변경된 내용은 일단 UNDO 영역에 생성된 뒤, 이전 버전의 데이터와 비교해서 병합됩니다. 

 


 

락과 트랜잭션(Transaction)

이전글에서는 트랜잭션의 정의에 대해 간략히 적기만 했지 예를 따로 들지 않았었는데요.

예시를 들어 좀 더 자세히 설명해 볼까 합니다.

 

트랜잭션은 '데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위'입니다.

예를 들어 결제 기능을 구현하기 위해서는 다음과 같은 코드를 실행해야 합니다.


1. 유저의 장바구니를 조회한다.
2. 결제하고자 체크한 상품, 상품 옵션, 선택 옵션 등 결제 대상이 되는 리소스를 조회한다.
3. 각 리소스의 재고가 구매하고자 하는 수량보다 많은지 본다.
4. 만약 상품 자체에 결제 이슈가 없는 경우라면 장바구니의 결제 금액 총합을 구한다.
5. 유저의 결제수단 정보를 조회한다.
6. 결제한다. ( = 보통 DB와 무관한 외부 API로 PG를 연동해서 결제를 한다고 해요( ex. 카카오, 토스 ))
7. 결제 정보를 기록하고 결제 내역 정보를 만든다.
8. 재고에서 구매한 숫자만큼을 빼준다. ( 다음번 유저가 구매를 할 때 정합성을 맞추기 위해 )

 

서비스의 복잡도에 따라 여러 테이블에 추가, 조회, 수정, 삭제 로직이 실행될 수 있겠죠.

하지만 유저 입장에선 관여하는 데이터베이스 테이블의 수가 얼마든, 실행되거나 되지 않아야 하는 하나의 작업 단위일 뿐입니다.

 

만약에 트랜잭션을 사용하지 않고, 위의 과정을 따라 결제 로직을 실행하다가 7번에서 실패하면 어떻게 될까요?

사용자의 돈으로 결제가 되었지만 결제 내역에서는 조회가 되지 않는 심각한 일이 벌어질 겁니다.

 

트랜잭션은  데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위로
Commit 되거나 Rollback 되어야 합니다.

 

그럼 위 말의 의미를 이해하셨을 것 같습니다.

 

 

트랜잭션 특성 (ACID)

트랜잭션은 아래 4가지 특성을 가집니다. 락은 이 특성들을 보장하기 위해 필요한 기능인거죠.

 

Atomicity(원자성)

트랜잭션의 연산은 DB에 모두 반영되든지 아니면 전혀 반영되지 않아야 한다.
완벽히 수행되지 않고 어느 하나라도 오류가 발생하면 트랜잭션 전부가 취소되어야 합니다.


단일한 쿼리처럼 동작해야 한다는 뜻입니다. 전부 성공하거나 전부 실패해야 합니다.

만약 도중에 실패한다면 나머지 성공했던 쿼리들을 모두 역순으로 되돌려서 문제가 없도록 만들어야 합니다.

아까 예로 든 것처럼  중간에 실패했을 때 원 상태로 되돌리지 않는다면 데이터의 정합성이 심각하게 망가지게 됩니다.

 

  • 결제를 했는데 재고 숫자를 바꾸는 데에 실패했다면?
  • 결제를 했는데 주문서를 만드는 데에 실패했다면?

 

Consistency(일관성)

트랜잭션 실행을 성공적으로 완료되었을 시 일관성 있는 데이터 베이스 상태를 유지하는 것.
일관성을 깨는 데이터에 대해서는 트랜잭션이 성공적으로 실행되지 않아야 한다는 의미입니다.

 

트랜잭션 이전과 이후 데이터베이스에 영향이 있어서는 안 됩니다.
예를 들어 데이터베이스의 모든 제약 조건(Primary Key, Foreign Key 등)이 유지되어야 한다는 거죠.

 

 

Isolation(독립성)

각각의 트랜잭션은 서로 간섭 없이 독립적으로 수행되어야 한다.
하나의 트랜잭션 실행 중에 다른 트랜잭션의 연산이 끼어들 수 없다.

 

다른 트랜잭션과 무관하게 독립적으로 실행되어야 합니다.

 

예를 들어 트랜잭션 A와 B가 있다고 해보겠습니다.

트랜잭션 A는 a1, a2, a3 작업을 수행하고,  트랜잭션 B는 b1, b2, b3 작업을 수행합니다.

 

두 트랜잭션의 실행 순서가 a1, b1, a2, b2, a3, b3 라고 한다면 데이터 정합성이 망가질지도 모릅니다. 

그러니 a1, a2, a3, b1, b2, b3 또는 b1, b2, b3, a1, a2, a3 순서로 실행되어야 한다는 것입니다.

A가 실행이 다 끝나고 B가 되거나, B가 실행이 다 끝나고 A가 되거나 말이죠.

 

락은 주로 독립성 보장을 위해 사용됩니다.

동시성 제어를 담당하고, 실행되는 트랜잭션 간의 상호작용을 관리합니다. 

 

지속성 ( Durability )

성공적으로 수행된 트랜잭션은 영원히 반영된다.
트랜잭션이 성공했다면, 데이터베이스에 어떤 시스템적인 문제가 발생하더라도 데이터는 영구적으로 보존되어야 한다.

 

로그파일을 이용한 복구가 예가 됩니다.
데이터베이스 시스템은 트랜잭션의 변경 사항을 로그 파일에 기록하는데요.

장애 발생 시에도 이러한 로그를 사용하여 데이터베이스를 이전 상태로 복구할 수 있습니다.

 

 


 

 

감사합니다.

 

공부한 내용을 복습/기록하기 위해 작성한 글이므로 내용에 오류가 있을 수 있습니다.

'DB' 카테고리의 다른 글

[DB] 인덱스에서 B+Tree를 사용하는 이유  (0) 2024.03.12
[DB] MySQL의 락 (feat. Auto Increment Lock)  (0) 2024.03.10
[DB] 정규형(Normal form)  (0) 2024.03.08
[DB] 인덱스(Index)  (0) 2024.03.07
[DB] SQL의 기본 문법  (0) 2024.03.04
댓글
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Total
Today
Yesterday