본문 바로가기

Node.js 도전기

Node.js_트랜잭션 (Transaction)

[간단 요약 !]
1. 트랜잭션이란? 
- 작업의 완전성을 보장해주기 위해 특정한 작업을 전부 처리하거나, 전부 실패하게 만들어 일관성을 보장해주는 기능
- 여러개의 작업(쿼리)를 하나의 작업 단위로 묶어서 처리

2. 왜 ? 
은행의 결제 시스템, 영화 예매 시스템 등 부분 업데이트가 되면 안되는 상황 즉 데이터의 일관성을 유지해야하는 상황에서 사용

3. 트랜잭션의 특징 ACID !
- 원자성(Atomicity) :
묶음 처리한 작업이 전부 성공하거나 실패해야한다는 특징 (나눠질 수 없는 단일 작업)
- 일관성(Consistency) :
트랜잭션 내부에서 처리되는 데이터의 일관성을 유지해야하는 특징 (실패한 상태로 데이터 방지 X)
- 격리성(Isolation) :
실행중인 경우 다른 트랜잭션에 의해 데이터가 변경되는 것을 방지하는 특징
- 지속성(Durability) :
트랜잭션이 성공적으로 커밋되면 데이터는 어떠한 상황에서도 보존되는 특징 (데이터 베이스에서)

4. 락(Lock)
- 동시성을 제어하기 위해 사용하는 기능
- 공유락(Shared Locks) / 읽기 락(READ Locks) :
다른 트랜잭션이 데이터를 읽는 것은 허용하지만 수정하는 것 금지
- 배타락(Exclusive Locks) / 쓰기 락(WRITE Locks) :
다른 트랜잭션이 데이터를 읽거나 수정하는 것 금지

5. 락킹 레벨(Locking Level) 
- 글로벌 락(Global Locks) :
데이터 베이스의 모든 테이블에 락을 걸어 현재 실행중인 트랜잭션 외 나머지 테이블 사용 불가
- 테이블 락(Table Locks) : 
작업중인 테이블을 동시에 수정하지 못하도록 설정
- 네임드 락(Named Locks) : 특정한 문자열을 점유(테이블 or 테이블 행 X)
- 메타데이터 락(Metadata Locks) : 작업중인 테이블의 동일한 행 및 데이터베이스 객체를 동시에 수정하지 못하도록 설정

6. 트랜잭션의 격리 수준(Isolation Level) 
- READ UNCOMMITTED : 가장 낮은 수준의 격리수준, 동시성이 높지만 일관성이 쉽게 깨질 수 있음
- READ COMMITTED : 다른 트랜잭션이 데이터 수정 중에는 데이터를 읽을 수 없음
-REPEATABLE READ : 읽기를 마치더라도 공유락을 풀지 않고, 트랜잭션이 완전히 종료될 때까지 락을 유지 
-SERIALIZABLE : 가장 높은 수준의 격리 수준으로 데이터를 읽거나 삽입, 새로운 데이터 추가 불가 

 

데이터 베이스에서 데이터를 관리할 때 하나의 데이터가 들어오면 이후에 추가로 연계되어 변동되는 데이터가 있을 경우가 있다. 

쉽게 예를 들면 은행에서 1,000원을 다른 사람에게 송금할 경우 내 계좌에서는 1,000원이 차감되고 다른 사람은 1,000원이 증가하게 되는 경우 처럼 말이다. 

 

하지만 이 때 예상치 못한 에러가 나서 차감 후 송금 과정에서 오류가 났다면? 

실제로 송금은 진행되지 않고 내 계좌에서 차감만 진행되어 기대했던 결과와 다른 결과가 나타날 것이다.

 

이러한 현상을 방지하기 위해 사용하는 것이 트랜잭션이다. 

 

#1.  트랜잭션이란? 

위 송금의 예시에서는 내 계좌에서 금액 차감, 다른 사람 계좌에서는 금액 증가 라는 2개의 작업(쿼리)이 필요하다.

이것을 따로 따로 실행할 경우 앞서 말한 오류 발생 시에 여러 문제들이 발생할 수 있어 트랜잭션이라는 개념이 필요하다. 

 

트랜잭션은 작업의 단위를 하나의 쿼리가 아닌 여러 개의 작업(쿼리)를 묶어서 하나의 작업 단위로 그룹화하여 처리하는 것을 말한다.

 

 

#2.  왜 사용하는가 !?

은행 송금의 예시처럼 특정 작업을 진행하다 오류가 나더라도 DB에 피해가 가지 않게끔하기 위해 사용하는데 

비슷한 상황으로는 작업한 내역을 저장하는 로깅작업, 영화 예매 시스템, 은행 결제 시스템 등이 있다. 

 

데이터의 일관성을 유지해야하는 상황들이다.

 

 

#3. 트랜잭션의 ACID 특징

1) 원자성(Atomicity) 

원자성이란 작업을 나눌수 없다는 의미로 트랜잭션 내에 있는 명령들이 모두 성공하거나 실패해야한다는 특징이다. 

즉 여러개의 쿼리로 보지 않고 하나로 묶어서 관리한다는 의미이다.

 

2) 일관성(Consistency)

트랜잭션 내의 데이터는 일관되어야하며, 에러가 발생하더라도 데이터의 상태가 일관성을 유지해야한다는 특징이다. 

만약 트랜잭션이 실패하더라도 실패한 상태로 데이터를 방치하지 않는다. 

 

작업이 실패할 경우 처음 상태로 RollBack하여 작업하기 이전 상태로 복구된다. 

 

3) 격리성(Isolation)

트랜잭션이 실행 중인 경우 다른 트랜잭션에 의해 데이터가 변경되는 것을 방지하는 특징이다. 

 

격리성에의 경우 사용중인 DB에 락(Lock)을 걸어 격리성을 구현하는데 

DB에 접속한 또 다른 클라이언트가 해당 DB오브젝트를 읽거나, 사용할 수 없도록 방지하여 데이터 무결성을 보장하게 된다.

 

격리성에서 동시성(Concurrency)과 격리 수준(Isolation Level)이라는 두가지 개념이 나타나게 된다 !

 

** 동시성이란?

여러 클라이언트가 동시에 하나의 데이터를 사용 및 공유하는 것 

다수의 사용자가 동일한 시스템을 공유하면서 발생하는 동시 접근 문제를 해결해야 한다. 

 

이로써 나온것이 Lock의 개념이며 하나의 자원에는 하나의 클라이언트만 점유할 수 있도록 하여,

다른 사용자가 접근할 수 없도록 만들어 자원을 공유하는 원인을 제거한다.

 

4) 지속성(Durability)

트랜잭션이 성공적으로 커밋되면 생성 혹은 수정된 데이터가 어떠한 상황에서도 보존되는 특징이다. 

(즉 데이터 베이스에 성공적으로 저장)

 

트랜잭션 수행 도중 시스템이 비정상 종료되더라도 시스템은 트랜잭션 로그를 통해 아직 커밋되지 않은 트랜잭션을 복구할 수 있다.

 

 

#4. 락(Lock)

1) 공유락(Shared Locks) | 읽기 락(READ Locks) 

- 다른 트랜잭션이 데이터 읽는 것은 허용하지만, 수정하는 것을 금지한다. 

- 해당 락을 사용하는 트랜잭션이 모든 작업을 수행하였다면 공유 락은 해제된다.

 

2) 배타락(Exclusive Locks) | 쓰기 락 (WRITE Locks) 

- 다른 트랜잭션이 데이터를 읽거나, 수정하는 것을 금지한다.

- 트랜잭션이 해당하는 데이터를 점유한 후 다른 트랜잭션이 해당하는 데이터에 접근할 수 없도록 만든다.

 

3) 락킹 레벨 (Locking Level)

- 글로벌 락(Global Locks) | 데이터베이스 락(Database Locks)

데이터 베이스의 모든 테이블에 락을 걸어 현재 트랜잭션을 제외한 나머지 트랜잭션들이 모든 테이블을 사용할 수 없도록 만든다. 

가장 높은 수준의 락을 가지고, 가장 큰 범위를 가지고 있다.

 

- 테이블 락 (Table Locks)

다른 사용자가 작업중인 테이블을 동시에 수정하지 못하게 한다.

 

- 네임드 락(Named Locks)

테이블이나 테이블의 행과 같은 DB오브젝트가 아닌, 특정한 문자열을 점유한다. 

 

- 메타데이터 락(Metadata Locks)

다른 사용자가 작업중인 테이블의 동일한 행 및 동일한 데이터베이스의 객체를 동시에 수정하지 못하도록 한다.

 

이처럼 락에는 다양한 락킹 수준이 있는데 잘못된 락을 설정하게 될 경우 모든 API가 작동하지 않는 교착상태(Dead Lock)가 발생하게 되어, 프로그램이 멈춰버리는 문제가 발생할 수 있다. 

 

 

#5. 격리 수준(Isolation Level)

1) Read Uncommited

- 커밋 되지 않은 읽기를 허용하는 격리 수준

- 가장 낮은 수준의 격리수준이고, 락을 걸지 않아 동시성이 높지만 일관성이 쉽게 깨질 수 있다. 

 

2) Read Commited

- 커밋된 읽기만을 허용하고, SELECT 문을 실행할 때 공유 락을 건다.

- 다른 트랜잭션이 데이터를 수정하고 있는 중에는 데이터를 읽을 수 없어 커밋되지 않은 읽기 현상이 발생하지 않는다. 

 

3) Repeatable Read

- 읽기를 마치더라도 공유락을 풀지 않으며, 트랜잭션이 완전히 종료될 때 까지 락을 유지한다. 

- 공유락이 걸린 상태에서 데이터를 수정하는 것은 불가능 하지만, 데이터를 삽입하는 것이 가능하다. 

- 팬텀읽기가 발생할 수 있다. (이미 삭제된 행에 해당하는 데이터를 읽는 것) 

 

4) Serializable

- 데이터를 읽는 동안 다른 트랜잭션이 해당하는 데이터를 읽거나 삽입할 수 없고, 새로운 데이터 추가도 불가능

- 가장 높은 수준의 격리 수준이므로, 동시성이 떨어지는 문제점 존재

 

 

오늘은 트랜잭션이라는 개념에 대해서 정리하였는데

아직은 좀 생소한 개념이다. 

 

앞으로 프로젝트를 진행하면서 사용하게될 내용으로 보이기에 추후 프로젝트에 대한 포스팅을 진행할 때 한번 예시를 정리해보도록 하겠다.