[CS] 트랜잭션( Transaction )

hyewon jeong·2023년 4월 3일
0

CS

목록 보기
15/22

1. ⚡️트랜잭션(Transaction)

❄️ 트랜잭션이란 여러 개의 작업을 하나로 묶은 실행 유닛

❄️ 트랜잭션이란 데이터베이스의 상태를 변환시키는 기능을 수행하기 위한 하나 이상의 쿼리를 모아 놓은 하나의 작업 단위를 말합니다.

❤️ 참고
POSTGRESQL 은 DDL(data definition language : 데이터 조작어)도 커밋을 해야한다!
오라클은 DDL은 커밋을 할 필요가 없다.

❄️ 데이터베이스 트랜잭션은 ACID라는 특성을 가지고 있습니다.

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

1-1. 📌 트랜잭션의 필요성

  1. 트랜잭션은 '거래'라는 뜻으로, 은행에서 입금과 출금을 하는 그 거래를 뜻합니다.
  2. A은행에서 출금하여 B은행으로 송금한다고 가정합니다.
  3. 송금하던 중 알 수 없는 오류가 발생하여 A은행계좌에서 돈이 빠져 나갔는데 B은행 계좌에는 되지 않았다.
  4. 이때 , 우리는 A은행 계좌에서 출금을 취소하거나, B계좌로 다시 송금하면된다.
  5. 하지만 이 방법은 번거롭고 더 심한 오류를 발생시킬 수 있습니다.
  6. 그래서 생각해낸
    해결책으로, 거래가 성공정으로 모두 끝난 후에야 이를 완전한 거래로 승한하고, 거래 도중 뭔가 오류가 발생했을때는 이 거래를 아예 처음부터 없었던 것처럼 거래를 되돌리는 것이다.
  7. 이렇게 거래의 안정성을 확보하는 방법이 트랜잭션입니다.
  8. 데이터베이스에선 테이블에서 데이터를 읽어 온후 다른테이블에서 데이터를 입력하거나 갱신, 삭제하는데 처리 도중 오류가 발생하면 모든 작업을 원상태로 되돌립니다.
    9.데이터베이스에선 처리과정이 모두 성공했을때만 최종적으로 데이터베이스에 반영합니다.

1-2. ⚡️트랜잭션의 종류

1-2-1. COMMIT

  • 모든 작업들이 정상적으로 처리되었따고 확정하는 명령어로 처리과정을 DB에 영구저장하는 것입니다.
  • Commit을 수행하면 이전 데이터가 완전히 UPDATE 된다.

1-2-2. ROLLBACK

  • Rollback은 작업 중 문제가 발생되어 트랜잭션의 처리과정에서 발생한 변경사항을 취소하는 명령어입니다.
  • 트랜잭션이 시작되기 이전의 상태로 되돌린다. 즉, 마지막 커밋을 완료한 시점으로 다시 되돌아갑니다.
  • 커밋하여 저장된 것만 복구합니다.
  • 트랜잭션은 이렇든 ALL-OR-Nothing 방식으로 DML 명령어들을 처리합니다.

1-3. ⚡️ ACID

ACID는 데이터베이스 내에서 일어나는 하나의 트랜잭션(transaction)의 안전성을 보장하기 위해 필요한 성질이다.
ACID는 주식거래, 금융업에서 중점적으로 사용된다.
=> 주식거래, 금융업에서는 관계형 데이터베이스를 이용한다.
관계형 데이터베이스를 사용하면 데이터베이스와 상호 작용하는 방식을 정확하게 규정할 수 있기 때문에,
데이터베이스에서 데이터를 처리할 때 발생할 수 있는 예외적인 상황을 줄이고, 데이터베이스의 무결성을 보호할 수 있다.

1-2-1. ❗️ Atomicity( 원자성 )

원자성이란 시스템에서 한 트랙잭션의 연산이 모두 성공하거나 또는 반대로 전부 실패되는 성질을 말합니다.
->은행에서
A계좌에서 10000원을 출금하고, B게좌에 10000원을 입금한다고 가정합니다.
이때, A계좌에서 10000원을 출금하는 것은 성공했지만 , B계좌에 입금하는 것이 실패되었을때 하나로 묶여잇는 작업들을 롤백합니다. (하나라도 실패시 하나로 묶여있는 작업들을 실패시켜 기존데이터를 보호 하는것)
(만약에 원자성이 보장되지 않았을때 , 문제가 어디서 발생했는지 알수 없다면 10000원은 사라져 버리기때문이다.)

1-2-2. ❗️ Consistency( 일관성 )

일관성은 데이터베이스의 상태가 일관되어야 한다는 성질이다.
일관성이란 크게 2가지 의미를 가집니다.

1) 첫 번째로, 트랜잭션이 커밋된 이후의 데이터베이스는 데이터베이스의 제약이나 규칙을 만족해야 한다는 뜻이다.
->사용자가 번호를 저장하려고 하는데, 이 번호에 UNIQUE 제약이 설정되어 있으면 중복된 사용자 번호를 저장할 수 없어야 한다.
2) 두 번째로, 트랜잭션의 작업이 애플리케이션에서 의도하고자 한 작동이 정상적으로 일어난다는 보장을 의미한다.
→ 재고가 떨어졌을 때, 더 이상 판매를 할 수 없도록 제한해야 한다.

1-2-3. ❗️ Isolation( 격리성 )

트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것을 의미합니다.

예를 들면, 부산의 지정 호텔에 남은 싱글룸 수가 10개였을 때 실제로 숙박하는 로직은 다음과 같다.

1.현재 빈 싱글룸의 수를 확인한다(SELECT)
2 빈 싱글룸 수에서 1을 빼고 결과를 빈 싱글룸 수로 되돌려 쓴다(UPDATE)
3. 이것을 사용자 A와 사용자 B가 동시에 수행하면 어떻게 될까? 2명이 방을 확보한다면 원래 빈 싱글룸 수는 2개가 줄어야 하지만, 같은 방을 동시에 확보하게 되면 빈 싱글룸 수는 1개만 줄어들게 된다.

이런 사태가 발생하는 것을 막기 위해, ⭐️⭐️⭐️데이터베이스에는 테이블에 대해 Lock(잠금)⭐️⭐️⭐️을 걸어서 후속처리를 Block하는 방법이 있다. 잠금 단위에는 테이블 전체, 블록, 행 등이 있는데, MySQL에서는 트랜잭션 처리를 할 때 주로 행 단위의 잠금 기능을 이용한다. 예를 들어, 앞의 두 가지 중 ‘1. 현재 빈 싱글룸 수를 확인한다’를 처리할 때 ‘SELECT ~ FOR UPDATE’를 실행하면 SELECT한 행에 잠금이 걸린다. 이렇게 되면 후속 처리는 해당 잠금이 해제될 때(COMMIT 또는 ROLLBACK)까지 대기하게 되며 올바른 처리를 계속할 수 있게 된다.

1-2-4. ❗️Durability(지속성)

지속성은 하나의 트랜잭션이 성공적으로 수행되었다면, 해당 트랜잭션에 대한 로그가 남아야하는 성질을 말한다.

  • 만약 런타임 오류나 시스템 오류가 발생하더라도, 해당 기록은 영구적이어야 한다는 뜻이다.
  • 예를 들어 은행에서 게좌이체를 성공적으로 실행한 뒤에, 해당 은행 데이터베이스에 오류가 발생해 종료되더라도 계좌이체 내역은 기록으로 남아야 한다.
    마찬가지로 계좌이체를 로그로 기록하기 전에 시스템 오류 등에 의해 종료가 된다면, 해당 이체 내역은 실패로 돌아가고 각 계좌들은 계좌이체 이전 상태들로 돌아가게 된다.

1-4. ⚡️ACID 원칙은 완벽히 지켜지지 않는다.

실제로는 ACID 원칙은 종종 지켜지지 않는다. 왜냐하면 ACID 원칙을 strict 하게 지키려면 동시성이 매우 떨어지기 때문이다. 그렇기 때문에 DB 엔진은 ACID 원칙을 희생하여 동시성을 얻을 수 있는 방법을 제공한다. 바로 transaction의 격리 수준(isolation level)이다. ACID중 Isolation(독립성) 원칙을 덜 지키는 level을 사용할수록 문제가 발생할 가능성은 커지지만, 동시에 더 높은 동시성을 얻을 수 있다. ANSI/ISO SQL standard에서 정의한 격리 수준에는 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABL이 있다.

2. ⚡️트랜잭션 격리 수준 (isolation level)

DB에서는 격리 수준(Isolation Level)을 설정함으로써 어떤 범위까지 Lock을 자동으로 걸도록 만들 지 결정할 수 있는 것이다.

동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지를 결정하는 것을 말한다.

격리 수준
격리 수준은 크게 4가지로 볼 수 있는데 아래로 순서대로 내려갈수록 트랜잭션간 고립 정도가 높아지며, 성능이 떨어지는 것이 일반적이다.

2-1. ⚡️ READ UNCOMMITTED

READ UNCOMMITTED 격리수준에서는 어떤 트랜잭션의 변경내용이 COMMIT이나 ROLLBACK과 상관없이 다른 트랜잭션에서 보여지는 것을 말한다.

그래서 다른 트랜잭션에서 Commit 하지 않아도 조회 했을때 데이터가 보여질 수 있다. 이를 더티 리드(Dirty Read) 라고 한다.

이런식으로 데이터 정합성에 문제가 많아, RDBMS 표준에는 격리수준으로 인정하지 않는다고 한다.

2-2. ⚡️READ COMMITTED

트랜잭션의 변경 내용이 COMMIT 되어야만 다른 트랜잭션에서 조회할 수 있다.
오라클 RDBMS에서 기본으로 사용하고 있다.

그렇지만 NON-REPETABLE READ 정합성 문제는 해결되지 않았다. 하나의 트랜잭션내에서는 SELECT를 수행할 경우 항상 같은 결과를 반환해야 하는데 중간에 커밋된 내용이 있으면 다른 결과를 내려줄 수 있기 때문이다

이런 문제가 발생할 수 있기 떄문에 격리수준에 의해 실행되는 SQL 문장이 어떤 결과를 출력할 지 정확히 예측하고 있어야 한다.

2-3. ⚡️REPEATABLE READ

트랜잭션이 시작하기 전에 커밋된 내용에 대해서만 조회할 수 있는 격리 수준이다.
MySQL DBMS에서 기본으로 사용하고 있다. 이러한 특성으로 NON-REPETABLE READ 정합성 문제는 어느 정도 해결이 됬다.

REPEATABLE READ 격리 수준에서는 시작된 시점에 데이터를 일관되게 보여줘야 하기 때문에 한 트랜잭션의 실행시간이 길어질수록 해당 시간만큼 멀티 버전을 관리해야 하는 단점이 있다.
그러나 실제로 오래 지속되는 경우가 없어 READ COMMITTED과의 성능 차이는 거의 없다고 한다.

2-4. ⚡️SERIALIZABLE

가장 단순하고 가장 엄격한 격리수준으로 InnoDB에서 기본적으로 순수한 SELECT 작업은 아무런 잠금을 걸지않고 동작하는데, 격리수준이 SERIALIZABLE일 경우 읽기 작업에도 잠금을 설정하게 되고, 이러면 동시에 다른 트랜잭션에서 이 레코드를 변경하지 못하게 된다.
이러한 특성 때문에 동시처리 능력이 다른 격리수준보다 떨어지고, 성능저하가 발생하게 된다.

https://jaeseongdev.github.io/development/2021/06/16/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EA%B2%A9%EB%A6%AC-%EC%88%98%EC%A4%80(Transaction-Isolation-Level)/
위 링크 꼭 읽어보기 ( 락 관련한 트랜잭션 격리수준 )

참고
https://hanamon.kr/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98%EC%9D%98-acid-%EC%84%B1%EC%A7%88/
https://velog.io/@syh0397/10.-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-BEGIN-COMMIT-ROLLBACK

profile
개발자꿈나무

0개의 댓글