Node 강의/숙련

2-6 트랜잭션(Transcation)

kagan-draca 2024. 9. 9. 15:07

1. 트랜잭션(Transcation)

트랜잭션(Transcation)은 작업의 완정성을 보장해주기 위해 사용되는 개념입니다.

특정한 작업을 전부 처리하거나, 전부 실패하게 만들어 데이터의 일관성을 보장해줍니다.

 

트랜잭션(Tanscation)을 사용하는 대표적인 이유는 작업의 단위를 하나의 쿼리에 종속하는 것이 아닌,

여러개의 작업(쿼리)을 묶어 하나의 작업 단위로 그룹화하여 처리하는 작업을 뜻합니다.

 

2. 트랜잭션(Transcation) 사용 이유?

 

여러분들은 트랜젝션을 이용해 다양한 문제 상황들을 해결할 수 있게 됩니다.

 

ex) 은행 계좌이체

 

1. A 고객의 계좌에서 1000원 차감

2. B 고객의 계좌에 1000원 추가

 

1번 작업 이후 2번 작업을 수행하던 중 에러가 발생하게 될 경우

A 고객 계좌에서만 1000원만 차감되는 문제가 발생합니다.

 

만약, 순서를 반대로 할 경우, B 고객의 계좌에

1000원이 증가되기만 하는 문제가 발생합니다.

 

이런, 부분 업데이트(Parital Update)와 같은 상황을 방지하기 위해 트랜잭션(Transaction)이 도입 됐습니다.

 

트랜잭션(Transaction)을 이용한다면 사용자가

항상 어플리케이션 실행을 완료 하도록 구성할 수 있게 됩고,

실행을 중단할 만한 치명적인 오류가 발생하더라도,

DB에 피해가 가지않아 더욱 안전하게 어플리케이션을 구성할 수 있게 됩니다.

 

3. 트랜잭션(Transcation) 특징(ACID)

트랜잭션의 특징(ACID)은 데이터베이스 트랜잭션이 안전하게 수행된다는 것을

보장하기 위한 특징들을 나열해 놓은 개념입니다.

 

ACID는 트랜잭션의 4가지 특징을 나타냅니다.

  • 원자성(Atomicity)
  • 일관성(Consistency)
  • 격리성(Isolation)
  • 지속성(Durability)

 

4. 원자성 (Atomicity)

원자성은 트랜잭션 내에서 실행되는 명령들을 하나의 묶음으로 처리하여,

내부에서 실행된 명령들이 전부 성공하거나, 아니면 모두 실패해야한다는 특징입니다.

→ 여기서, “원자성”이란, 나눠질 수 없는 단일 작업이라는 것을 의미합니다.

 

트랜잭션에서 실행되는 쿼리마다 하나의 작업 단위로 보지않고,

여러개의 작업들을 묶어 하나의 작업단위로 보게 됩니다.

 

ex) 계좌 금액 참감과 금액 증가를 하나의 계좌 이체라는 기능으로 묶어서 관리

 

결국, 원자성이라는 특징을 이용해 여러분들은 각각의 쿼리를 별도로 실행하는 것이 아니라,

동시에 실행해야하는 여러개의 쿼리를 묶어서 관리할 수 있게 됩니다.

 

 

5. 일관성 (Consistency)

일관성(Consistency)은 트랜젝션 내부에서 처리되는 데이터의 일관성을 유지해야하는 특징입니다.

만약 작업이 성공할 경우 아무런 문제가 발생하지 않고, 실패하더라도 작업을 진행하던 도중

실패한 상태로 데이터를 방치하지 않는 특징입니다.

 

일관성(Consistency)의 특징은 트랜잭션 내의 데이터는 일관되어야하며, 에러가 발생하더라도

데이터의 상태가 일관성을 유지해야 한다는 특징입니다.

 

만약 일관성이 지켜지지 않을 경우 여러분들은 트랜잭션을 이용하더라도 언제 데이터가 파손될지

모르는 불안감을 가진 체 작업을 해야합니다.

 

ex) 강의 등록

 

1. 강의(Courses) 테이블에서 강의를 생성합니다.

2. 생성된 강의 데이터를 참조하는 강의 목록(CourseUnit) 테이블에 강의 영상을 업로드 합니다.

3. 강의 목록(CourseUnit) 테이블에 모든 강의 영상을 업로드 하였다면 COMMIT

 

만약, 첫번째 강의 테이블에 강의를 생성하는 것은 성공했지만,

두번째 강의 목록 테이블에서 모든 강의 영상을 삽입하는데 실패하였다면,

RollBack이 실행돼 강의(Coureses) 테이블과 강의 목록(CourseUnit) 테이블에는

트랜잭션 시작 전 상태로 복구 됩니다.

 

이렇게, 데이터는 생성되지 않거나, 생성되는 상황이 발생해 일관성을 유지해야 합니다.

 

6. 격리성 (Isolaion)

 

격리성(Isolation)은 트랜잭션이 실행 중인 경우 다른 트랜잭션에 의해 데이터가 변경되는 것을 방지하는 특징입니다.

트랜잭션이 완전히 수행되거나 완전히 수행되지 않은 상태를 외부에서 참조할 수는 있지만,

트랜젝션의 중간 과정이나 중간 결과를 볼 수 없도록 하는 특징입니다.

 

격리성(Isolation)의 경우, MySQL에서는 사용 중인 DB 오브젝트에 락(Lock)을 걸어

격리성을 구현하게 됩니다. 락(Lock)을 건 상태는 DB에 접속한 다른 클라이언트가

해당 DB 오브젝트를 읽거나, 사용할 수 없도록 방지하여, 데이터 무결성을 보장하게 됩니다.

(여기서 운영체제 시간에 배운 락(Lock)이 나올줄이야...)

 

 

격리성이란 특징에서 동시성(Concurrency)격리 수준(Isolation Level)라는 두 가지 중요한 개념이 나타납니다.

 

동시성(Concuurency)은 여러 클라이언트가 동시에 하나의 데이터를 사용공유 하는 것을 뜻 합니다.

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

 

7. 지속성 (Durability)

 

지속성(Durability)은 트랜잭션이 성공적으로 커밋된 후,

해당 트랜잭션에 의해 생성 또는 수정된 데이터가

어떠한 상황에서도 보존되는 특징입니다.

 

다시 말해, 트랜잭션이 완료되면 결과는 데이터베이스에 영구적으로 저장되며,

이후 시스템에 어떠한 문제가 생기더라도 데이터는 손상되지 않습니다.

 

COMMIT 명령을 통해 영구적으로 저장, 비정상 종료되더라도,

시스템은 트랜잭션 로그(Transaction Log)를 통해 아직 커밋되지

않은 트랜잭션을 복구할 수 있습니다.

 

7. MySQL의 트랜잭션 살펴보기

 

-- 트랜잭션을 시작합니다.

START TANSACTION;

 

-- 성공시 작업 내역을 DB에 반영합니다.

COMMIT;

 

-- 실패시 START TRANSACTION이 실행되기 전 상태로 작업 내역을 취소합니다.

ROLLBACK;

 

 ex)

CREATE TABLE IF NOT EXISTS SPARTA
(
    spartaId      INT(11)      NOT NULL PRIMARY KEY AUTO_INCREMENT,
    spartaName    VARCHAR(255) NOT NULL,
    spartaAddress VARCHAR(255) NOT NULL
);

-- 1번째 트랜잭션을 실행합니다.
START TRANSACTION;

-- SPARTA 테이블에 더미 데이터 3개를 삽입합니다.
INSERT INTO SPARTA (spartaName, spartaAddress)
VALUES ('SPARTA1', 'SEOUL'),
       ('SPARTA2', 'BUSAN'),
       ('SPARTA3', 'DAEGU');

-- 1번째 트랜잭션을 DB에 적용합니다.
COMMIT;


-- 2번째 트랜잭션을 실행합니다.
START TRANSACTION;

-- SPARTA 테이블에 더미 데이터 3개를 삽입합니다.
INSERT INTO SPARTA (spartaName, spartaAddress)
VALUES ('SPARTA4', 'SEOUL'),
       ('SPARTA5', 'BUSAN'),
       ('SPARTA6', 'DAEGU');

-- 2번째 트랜잭션을 롤백합니다.
ROLLBACK;

-- 테이블의 상태를 확인합니다.
SELECT * FROM SPARTA;

 

위의 코드를 실행시키면,

 

-- 1번째 트랜잭션을 실행합니다.
START TRANSACTION;

-- SPARTA 테이블에 더미 데이터 3개를 삽입합니다.
INSERT INTO SPARTA (spartaName, spartaAddress)
VALUES ('SPARTA1', 'SEOUL'),
       ('SPARTA2', 'BUSAN'),
       ('SPARTA3', 'DAEGU');

-- 1번째 트랜잭션을 DB에 적용합니다.
COMMIT;

 

부분은 COMMIT으로 DB에 정상 반영된 것을 확인 가능하지만,

 

-- 2번째 트랜잭션을 실행합니다.
START TRANSACTION;

-- SPARTA 테이블에 더미 데이터 3개를 삽입합니다.
INSERT INTO SPARTA (spartaName, spartaAddress)
VALUES ('SPARTA4', 'SEOUL'),
       ('SPARTA5', 'BUSAN'),
       ('SPARTA6', 'DAEGU');

-- 2번째 트랜잭션을 롤백합니다.
ROLLBACK;

은 ROLLBACK으로 DB에 반영이 안 된 것을 확인할 수 있습니다.

 

8. 락(Lock)의 종류

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

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

- READ 전용 락이라고 불리기도 하며, 해당 락을 사용하는 트랜잭션이

모두 작업을 수행하였다면 공유 락은 해제 됩니다.

# 트랜잭션을 시작합니다.
START TRANSACTION;

# SPARTA 테이블을 조회할 때, 해당 데이터들에 공유 락을 설정합니다.
SELECT * FROM SPARTA LOCK IN SHARE MODE;

 

 

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

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

- WRITE 전용 락이라고 부리며, 트랜잭션이 해당하는 데이터를

점유한 후 다른 트랜잭션이 해당 데이터에 접근할 수 없도록 만듭니다.

# 트랜잭션을 시작합니다.
START TRANSACTION;

# SPARTA 테이블을 조회할 때, 해당 데이터들에 배타 락을 설정합니다.
SELECT * FROM SPARTA FOR UPDATE;

 

 

9. 락킹 수준(Locking Level)

 

1) 글로벌 락(Global Locks) | 데이터베이스 락(DataBase Locks)

 

- 데이베이스의 모든 테이블에 락을 걸어,

현재 트랜잭션을 제외한 나머지 트랜잭션들이

모든 테이블을 사용할 수 없도록 만듭니다.

 

- 가장 높은 수준의 락을 가지고 있으며,

  가장 큰 범위를 가지고 있습니다.

 

ex)

# 글로벌 락을 획득합니다.
# MySQL 서버에 존재하는 모든 테이블에 락을 겁니다.
FLUSH TABLES WITH READ LOCK;

 

2) 테이블 락(Table Locks)

 

- 다른 사용자가 작업중인 테이블을 동시에 수정하지 못하도록 합니다.

 

ex)

# SPARTA 테이블에 테이블 락을 설정합니다.
LOCK TABLES SPARTA READ;

 

3) 네임드 락(Named Locks)

 

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

 

ex)

# sparta_name 문자열을 획득합니다.
# 만약, 10초 동안 획득 하지 못한다면, NULL을 반환합니다.
SELECT GET_LOCK('sparta_name', 10);

 

4) 메타데이터 락(Metadata Locks)

 

- 다른 사용자가 작업 중인 테이블의 동일한 행 및 동일한 데이터베이스의 객체를

  동시에 수정하지 못하도록 합니다.

 

ex)

# 테이블 구조를 변경할 때, MySQL은 내부적으로 메타데이터 락을 설정합니다.
ALTER TABLE SPARTA ADD COLUMN Age Int;

 

락은 다양한 락킹 수준(Locking Level)을 가지고 있는데,

잘못된 락 설정을 하게 될 경우 여러분들은 모든 API가 동작하지 않는

교착 상태(Dead Lock)가 발생하게 됩니다.

 

add) 교착 상태와 해결 방법은

https://kagan-draca.tistory.com/227

 

2024년 8월 27일 강의 및 추가 학습(게임 서버의 역할, 상호 작용, 하는 일, 자격)

게임 서버의 역할싱글 플레이에서 모든 입출력과 연산 처리는한 대의 컴퓨터에서 수행한다. 따라서, 네트워크 자체가 필요 없기 때문에컴퓨터는 다음과 같은 과정을 반복한다. 1. 입력받기 :

kagan-draca.tistory.com

에 포함 돼 있습니다.

 

10. 트랜잭션의 격리 수준(Isolation Level)

 

여러 트랜잭션이 동시에 처리될 때 다른 트랜잭션에서 변경 및 조회하는

데이터를 읽을 수 있도록 허용하거나 거부하는 것

 

READ UNCOMMITTED

  • 커밋 되지 않은 읽기(Uncommitted Read)를 허용하는 격리 수준입니다.
  • 가장 낮은 수준의 격리수준이며, 락을 걸지 않아 동시성이 높지만 일관성이 쉽게 깨질 수 있습니다.

READ COMMITTED

  • 커밋 된 읽기(Committed Read)만을 허용하고, SELECT 문을 실행할 때 공유락을 겁니다.
  • 다른 트랜잭션이 데이터를 수정하고 있는 중에는 데이터를 읽을 수 없어 커밋되지 않은 읽기현상이 발생하지            않습니다.

REPEATABLE READ

  • 읽기를 마치더라도 공유락풀지 않으며, 트랜잭션이 완전히 종료될 때 까지 락을 유지합니다.
  • 공유락이 걸린 상태에서 데이터를 수정하는 것은 불가능하지만, 데이터를 삽입하는 것이 가능해집니다. 그로인해      팬텀 읽기가 발생할 수 있는 문제점이 있습니다.

SERIALIZABLE

  • 데이터를 읽는 동안 다른 트랜잭션이 해당 데이터를 읽거나 삽입할 수 없고, 새로운 데이터를 추가하는 것 또한 불가능합니다.
  • 가장 높은 수준의 격리 수준이므로, 동시성이 떨어지는 문제점이 존재합니다.

 

- 커밋되지 않은 읽기 (Uncommitted Read)

 

커밋되지 않은 읽기(Uncommitted Read)는 다른 트랜잭션에 의해 작업중인 데이터를 읽게 되는 것을 나타냅니다.

만약 커밋되지 않은 읽기가 발생할 경우, 의도치 않은 데이터를 참조하게 되어 데이터의 일관성이

깨지게 되는 상황이 발생하게됩니다.

 

- 팬텀 읽기 (Phantom Read)

 

트랜잭션을 수행하던 중 다른 트랜잭션에 의해 삭제된 데이터팬텀행(Phantom Rows)이라고 합니다.

여기서, 팬텀행에 해당하는 데이터를 읽는 것을 팬텀 읽기(Phantom Read)라고 부릅니다.