본문 바로가기
Data/DB

[MySQL] Transaction의 모든 것 | LIM

by forestlim 2022. 5. 21.
728x90
반응형

MySQL/MariaDB의 InnoDB 스토리지 엔진은 Transaction(트랜잭션) 기능을 지원한다.

📌  Transaction 단어의 뜻은 이러하다.

  • 거래, 매매
  • 처리과정

컴퓨터 과학 분야에서의 트랜잭션은 “더이상 분할이 불가능한 업무처리의 단위" 를 뜻한다.

 

✔️ 이것은 하나의 작업을 위해 더이상 분할될 수 없는 명령어들의 모음, 즉 한꺼번에 수행되어야 할 일련의 연산모음을 의미한다.

 

예로, 사용자가 바라보는 db에 이런 작업을 한다고 하자

매일 오후 11시에 delete 후 새로운 정보를 합해서 insert 하는 작업이 있다.

이 작업은 delete 후 insert 가 완벽히 하나의 작업으로 끝나야 사용자는 새로운 정보를 받아볼 수 있다.

transaction을 이상하게 묶으면

  • delete 도중 사용자가 접속하여 필요한 정보가 안보인다든지
  • insert 도중 다른 데이터가 insert 되는 경우 이상한 정보를 받아볼 수 있는 것이다.

따라서 delete → insert 되는 동안 delete에 속해 있는 record를 다른 transaction이 무언가 업데이트하려고 하면 그 작업을 막는 것이다. 

테이블에 데이터를 입력하거나 갱신, 삭제하는 도중에 오류가 발생하면, 결과를 재반영하는 것이 아니라 모든 작업을 원상태로 복구하고, 처리 과정이 모두 성공하였을 때만 그 결과를 반영하는 것이 데이터베이스에 있어서의 트랜잭션이다.

따라서 트랜잭션을 쓰는 이유는 데이터의 일관성을 유지하면서 안정적으로 데이터를 복구하기 위함이다.


📌 트랜잭션 특징

mysql에서는 autocommit을 통해 INSERT, DELETE, UPDATE, SQL 명령문을 통해 데이터의 상태를 바꿀때마다 내부적으로 자동적으로 commit을 실행하여 변경된 내역을 데이터베이스에 반영하는 것이다.

 

트랜잭션 연산에는 Commit과 Rollback 이 있다.

  • commit: 하나의 트랜잭션이 작업을 성공적으로 수행하여 데이터베이스가 다시 일관된 상태를 가질 때 트랜잭션이 완료되었다는 메시지를 알려주는 연산
  • rollback: 하나의 트랜잭션이 작업 수행도중 실패하여 데이터베이스의 일관성이 깨지게 된 경우 작업이 수행되기 이전의 데이터베이스의 일관성 상태로 돌아가기 위해 트랜잭션에서 수행했던 작업들을 취소시키는 연산

트랜잭션 특징(ACID)

  • Atomicity(원자성)
    • 트랜잭션이 수행되던 도중 비정상적으로 종료되게 되면 종료되기 이전 정상적으로 수행되었던 작업이 데이터베이스에 반영된다면 데이터베이스를 신뢰할 수 없을 것이다.
    • 위에서 예시로 들었던 상황처럼 delete 는 정상적으로 수행이 되었고 insert 도중 에러가 발생했을 시 정상적으로 수행된 delete 만 반영이 되면 안되는 것이다. 아예 delete 하기 이전 상태로 돌아가야 한다.
    • 따라서, 트랜잭션을 통해 변경되는 데이터베이스의 신뢰성을 보장하기 위해 모든 트랜잭션 작업들이 정상적으로 수행된 후 반영되든지 모든 작업이 수행되지 않고 이전 데이터베이스 상태를 유지해야 한다.
  • Consistency(일관성)
    • 트랜잭션이 진행되는 동안에 데이터베이스가 변경되더라고 업데이트된 데이터베이스로 트랜잭션이 진행되는 것이 아니라, 처음에 트랜잭션을 진행하기 위해 참조한 데이터베이스로 진행된다.
  • Isolation(독립성)
    • 일련의 다른 트랜잭션 작업들이 동시에 수행되는 경우 각각의 트랜잭션 연산에 간섭없이 독립적으로 수행되어야 한다.
    • 하나의 특정 트랜잭션이 완료될때까지, 다른 트랜잭션이 특정 트랜잭션의 결과를 참조할 수 없다.
  • Durability(지속성)
    • 트랜잭션이 정상적으로 완료된 이후에는 데이터베이스 내에 작업이 영구적으로 반영되어 있어야 한다.

📌  트랜잭션 상태

트랜잭션의 연산과정의 단계는 이러하다.

  1. Active (활동) : 트랜잭션이 시작했고 동작중인 상태를 의미한다.
  2. Partially Committed (부분 완료) : 트랜잭션에서 실행한 모든 쿼리문이 완료되었지만, 최종적으로 데이터베이스에 반영하지 않은 상태 (Commit 명령을 수행하지 않은 상태)를 의미한다.
  3. Committed (완료) : 트랜잭션 작업이 정상적으로 마무리되어 종료된 상태를 의미한다.
  4. Failed (실패) : 트랜잭션이 작업 수행 도중 비정상적으로 종료되어 실패한 상태를 의미한다.
  5. Aborted (철회) : 트랜잭션이 실패 후 트랜잭션이 취소되고 이전 상태로 돌아간 상태를 의미한다.

📌  트랜잭션 격리 레벨(Transaction Isolation Level)

 

LV1: Read-Uncommitted
  • 아직 커밋되지 않은 트랜잭션에서 처리중인 데이터를 다른 트랜잭션에서 읽는 것을 허용하는 격리 레벨
  • 정합성에 문제가 많은 격리수준이기 때문에 사용하지 않는 것을 권장한다.
    - Dirty Read, Non-Repeatable Read, Phantom Read 이상 현상이 모두 일어난다.
  • Commit이 되지 않는 상태지만 Update 된 값을 다른 트랜잭션에서 읽을 수 있다.
LV2: Read-Commited
  • RDB에서 대부분 기본적으로 사용되고 있는 격리수준
  • Dirty Read와 같은 현상은 발생하지 않는다.
  • 실제 테이블 값을 가져오는 것이 아니라 Undo 영역에 백업된 레코드에서 값을 가져온다.
  Read-Committed 의 문제는?

  • 하나의 트랜잭션내에서 똑같은 select 쿼리를 실행했을 때는 항상 같은 결과를 가져와야 하는 Repeatbale Read 의 정합성에 어긋난다.
  • 이러한 문제는 주로 입금, 출금 처리가 진행되는 금전적인 처리에서 주로 발생한다.
    - 데이터의 정합성은 깨지고, 버그는 찾기 어려워짐
    - 입금과 출금 처리가 계속 진행될 때 다른 트랜잭션에서 오늘 입금된 금액의 총합을 조회한다고 가정했을 때 Repeatable Read가 보장되지 않기 때문에 총합을 계산하는 SELECT 쿼리는 실행될 때마다 다른 결과를 가져오게 되는 것
LV3: Repeatable-Read
  • InnoDB 스토리지 엔진은 트랜잭션이 Rollback 될 경우를 대비하여 변경 전 데이터를 UNDO에 백업해두고 실제 레코드 값을 변경하게 됨. 그리고 트랜잭션이 Commit을 하기 전에 다른 세션에서 해당 데이터를 조회 시 Undo를 참조하여 이전 값을 보여주는 것을 MVCC(Multi Version Concurrency Control) 라고 함
  • Undo 공간에 백업해두고 실제 레코드 값을 변경
    - 백업된 데이터는 불필요하다고 판단되는 시점에 주기적으로 삭제
    - MVCC를 보장하기 위해서 실행 중인 트랜잭션 가운데 가장 오래된 트랜잭션보다 앞선 Undo영역의 데이터는 삭제할 수 없다.

    한 사용자가 Begin으로 트랜잭션을 시자가하고 조회하고 장시간 트랜잭션을 종료하지 않았다면 Undo 역역이 백업된 데이터로 인하여 무한정 커질 수 있게 된다.
    Undo 에 백업된 레코드가 많아지면 MySQL 서버의 처리 성능이 떨어질 수 있다.
  Repeatable-Read 의 문제는?

  • Phantom Read
    - 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상
    - 이를 방지하기 위해서는 쓰기 잠금을 걸어야 한다.
하지만 InnoDB에서는 독특한 특성 때문에 Repeatable Read 의 격리 수준에서도 Phantom Read 가 발생하지 않는다.
LV4: Serializable 트랜잭션에서 사용중인 데이터를 다른 트랜잭션에서 접근할 수 없도록 하는 격리 레벨이다. 트랜잭션의 ACID 성질이 엄격하게 지켜지나 성능을 가장 떨어진다.

 


💡  autocommit 설정

MYSQL 트랜잭션 전역 설정

MYSQL에서는 디폴트로 auto commit 이 설정 되어 있다. 명령어를 한번, 세미콜론을 찍을 때마다 DB에서 자동으로

commit 해주는 시스템이다.

이를, 아예 MYSQL 기본 commit 방식을 바꿀 수 있다.

✔️ autocommit=0

✔️ autocommit=1

 


Reference

728x90
반응형

댓글