트랜잭션 이란 ?
트랜잭션(Transaction)은 데이터베이스(DB)의 상태를 변화시키기 위해 수행하는 작업의 단위를 의미합니다.
쉽게 설명하자면 여러 개의 작업을 하나로 묶은 실행 Unit이라고 합니다.
데이터 베이스의 상태를 변화시킨다는 말은 어렵게 이해하실 필요가 없습니다.
한번씩 써오셨던 질의어(SQL)를 사용하여 DB에 접근하는 것을 의미합니다.
- Insert (C)
- Select (R)
- Update (U)
- Delete (D)
이 부분에서 주의해야 할 점은 작업의 단위는 select * from lab 처럼 한 문장이 아닐 수도 있다는 점입니다.
작업 단위는 많은 질의어 명령문들을 사람이 정하는 기준에 따라 정하는 것을 의미합니다.
A양이 B군에게 계좌이체를 하는 상황을 예시로 들어 보겠습니다.
- A양의 통장계좌에서 3만 원이 출금된다.
- B군의 은행명과 계좌번호가 맞는지 확인한다.
- B군의 통장계좌에 3만 원이 입금된다.
예시를 데이터 베이스의 작업으로 생각해 봅니다.
- A양의 통장 계좌의 정보를 Select 한다.
- A양의 통장 계좌에서 3만 원 이상이 있는지 Select 한 후, 계좌잔액을 Update 한다.(-3만 원)
- B군의 은행명과 계좌번호가 존재하는지 Select 한다.
- 존재한다면, B군의 계좌에 Update 한다.(+3만 원)
이때의 작업 단위는 Select와 Insert문 두 개를 합친 것입니다. 이러한 작업단위를 하나의 트랜잭션이라고 합니다.
이때 A양의 계좌잔액이 3만 원 이상이 아니라면 정상적으로 계좌이체가 되지 않는 게 상식적인 것처럼 하나의 작업 단위가 모두 정상적으로 실행되지 않는다면 계좌이체 실패를 알려주어야 합니다.
트랜잭션이 있으면 좋은 점
트랜잭션은 가능한 최대한의 데이터 안전성과 무결성을 보장해 줍니다.
쉽게 설명하자면 작업 하나가 일부분만 완료되는 바람에 일관적이지 않은 상태가 되는 불상사를 일어나지 않게 해 준다는 뜻입니다.
예를 들어 트랜잭션이 없다고 가정해 보겠습니다.
데이터베이스 테이블에 데이터를 넣는 중에 예기치 못한 정전이 된다고 했을 때 데이터 중 일부는 저장이 되고, 일부는 저장되지 않는 사태가 발생할 수 있습니다. 이렇게 된다면 데이터베이스는 일관성 없는 상태가 되어 복구하기도 어려울 뿐만 아니라 시간도 오래 걸리게 됩니다.
트랜잭션의 특징 (ACID)
- 원자성 (Atomicity)
- 일관성 (Consistency)
- 독립성, 격리성, 고립성 (Isolation)
- 지속성 (Durability)
1. 원자성
원자성이란 시스템에서 한 트랜잭션의 연산들이 모두 성공하거나, 반대로 모두 실패하는 성질을 말합니다.
즉, 원자성은 작업이 모두 반영되거나 모두 반영되지 않음으로써 결과를 예측할 수 있어야 합니다.
하나의 단위로 묶여있는 여러 작업이 부분적으로 실행된다면, 업데이트가 일어났지만,
누가 업데이트했는지 모르거나, 업데이트 날짜가 누락되는 등 데이터가 손상될 수 있습니다.
위에서 A양, B군의 계좌 이체를 예로 들어 보겠습니다.
1. A양 계좌에서 출금된다.
2. B군 계좌에 입금 된다.
계좌 이체를 하려 하는데, A양의 계좌에서는 출금이 이루어지고, B 군의 계좌에는 입금이 되지 않았다고 가정합니다.
어디서 문제가 발생되었는지 파악할 수 없다면, A양의 계좌에서 출금된 3만 원은 사라져 버리게 됩니다.
만약 은행에서 이런 일이 발생한다면, 어느 누구도 그 은행을 사용하지 않게 될 것입니다.
A양의 계좌에서 출금하는 일에 성공했지만, B군의 계좌에 입금하는 작업에 실패한다면 A양의 계좌에서 출금하는 작업을 포함하여 모든 작업이 원점으로 돌아가는 것이 원자성(Atomicity)입니다.
이때, 둘 중 하나라도 작업이 실패한다면, 하나의 단위로 묶여있는 모든 작업이 실패하게 만들어 기존 데이터를 보호합니다.(RollBack)
특정 쿼리를 실행하였는데 부분적으로 실패하는 부분이 있다면, 전부 실패하도록 구현되어 있습니다.
2. 일관성
일관성은 데이터베이스의 상태가 일관되어야 한다는 성질입니다.
일관성은 하나의 트랜잭션 이전과 이후, 데이터베이스의 상태는 이전과 같이 유효해야 합니다.
즉, 트랜잭션이 일어난 이후의 데이터베이스는 데이터베이스의 제약이나 규칙을 만족해야 합니다.
예를 들어 모든 회원은 이메일이 중복이 되지 않아야 하는 Unique와, 빈값이 되면 안 되는 NotNull인 데이터베이스의 제약이 있다고 가정해 보겠습니다.
다음과 같은 트랜잭션은 Consistency(일관성)을 위반합니다.
1. 이미 회원의 이메일이 codej1004@gmail.com 이 존재하는데 같은 이메일로 회원이 추가되는 쿼리
2. 이메일 변경 기능을 사용하는데 이미 사용하고 있는 이메일로 인증을 받아, 이메일이 변경되는 쿼리
3. 이메일 입력 없이 회원 가입을 하는 쿼리
4. 기존 회원의 이메일을 삭제하는 쿼리
데이터베이스는 유효한 상태는 다를 수 있지만, 데이터의 상태에 대한 일관서은 변하지 않아야 합니다.
위의 예시는 '이메일은 중복이 되면 안 된다', '이메일은 필수 값이다'라는 제약을 위반합니다.
따라서 예시의 트랜잭션이 일어난 이후의 데이터베이스는 일관되지 않는 상태를 가지게 됩니다.
3. 격리성, 고립성, 독립성
격리성, 고립성, 독립성은 모두 같은 Isolation을 의미합니다. 보통은 격리성으로 많이 부르는 것 같습니다.
격리성은 둘 이상의 트랜잭션이 동시에 실행되고 있을 때 다른 트랜잭션으로부터 독립되어야 한다는 성질입니다.
실제로 동시에 여러 개의 트랜잭션들이 수행될 때,
각 트랜잭션은 격리되어 있어 연속으로 실행된 것과 같은 동일한 결과를 나타냅니다.
A양, B군, C양의 계좌이체 예시를 들어보겠습니다.
A양의 계좌 잔액이 5만 원이라고 가정해 보겠습니다.
A양의 계좌로부터 B군에게 3만 원을, C양에게 3만 원을 동시에 이체하는 경우가 존재한다고 가정해 봅니다.
이때, B군에 먼저 송금한 뒤, C양에 보내는 결과는 동일해야 합니다.
동시에 트랜잭션을 실행한다고 해서 B군과 C양에 각각 3만 원을 송금한다고 하여 마이너스 통장이 되는 것이 아닙니다.
B군, C양에게 송금 작업을 연속으로 실행하는 것과 동일한 결과가 나타나야 합니다.
격리성을 지키는 각 트랜잭션은 철저히 독립적이기 때문에, 다른 트랜잭션의 작업 내용을 알 수 없습니다.
그리고, 트랜잭션이 동시에 실행 될 때와 연속으로 실행될 때의 데이터 베이스 상태가 동일해야 합니다.
4. 지속성
지속성은 하나의 트랜잭션이 성공적으로 수행되었다면, 해당 트랜잭션에 대한 로그가 남아야 하는 성질을 말합니다.
만약 런타임 오류나 시스템적인 오류가 발생하더라도, 해당 기록은 영구적이어야 한다는 뜻입니다.
예를 들어 A양의 계좌이체가 성공적으로 실행이 되었을 때, 해당 은행에서 전산오류가 발생하여 종료되더라도, 계좌이체 내역은 기록으로 남아야 합니다.
마찬가지로 계좌이체를 로그로 기록하기 전에 시스템 오류 등의 이유로 종료가 된다면, 해당 이체 내역은 실패로 돌아가고, 각 계좌들은 계좌이체 이전 상태들로 돌아가게 됩니다.
트랜잭션의 Commit, Rollback, SavePoint
Commit
하나의 트랜잭션이 성공적으로 끝이 났으며, 데이터베이스가 일관성에 있는 상태에 있을 때, 하나의 트랜잭션이 끝났다는 것을 알려주는 연산의 한 종류입니다.
추가, 변경된 데이터를 테이블에 영구적으로 반영하는 것을 의미합니다.
- Commit 전에는 단지 메모리 Buffer에만 영향을 받았기 때문에, 데이터의 변경 이전 상태로 복구가 가능합니다.
- Commit 후에는 변경사항이 DB에 반영이 되며, 이전 데이터는 영원히 사라집니다.
- Commit 이전에, 다른 사용자는 현재 사용자가 수행한 명령문의 결과를 볼 수 없습니다.
- Commit이후 모든 사용자가 결과를 확인이 가능합니다.
- Commit 이전에, 변경된 행은 잠금(Lock)이 설정되어서 다른 사용자가 변경할 수 없습니다.
- Commit 이후에, 잠금(Lock)이 풀리고 다른 사용자들이 행을 조작합니다.
- 애플리케이션의 정상적인 종료, 비정상적인 종료로 인하여 DB접속이 단절되었을 때는 자동으로 Rollback 됩니다.
Rollback
하나의 트랜잭션 처리가 비정상적으로 종료되어 트랜잭션의 원자성이 지켜지지 않은 경우, 트랜잭션을 처음부터 다시 시작하거나, 트랜잭션의 부분적으로만 연산된 결과를 다시 취소시킵니다.
테이블 내 입력한 데이터나, 수정한 데이터, 삭제한 데이터에 대하여 Commit 이전에는 변경 사항을 취소할 수 있는데,
데이터베이스에서는 롤백(Rollback) 기능을 사용하면 됩니다.
롤백은 데이터 변경 사항이 취소되어 데이터의 이전 상태로 복구되며, 관련된 행에 대한 잠금(Lock)이 풀리게 되고,
다른 사용자들이 데이터 변경을 할 수 있게 됨을 의미합니다.
SavePoint
저장점(SavePoint)은 롤백할 때 트랜잭션에 포함된 전체 작업을 롤백하는 것이 아니라
현시점에서 SavePoint까지 트랜잭션의 일부만 롤백할 수 있습니다.
따라서, 복잡한 대규모 트랜잭션에서 에러가 발생하였을 때 SavePoint까지의 트랜잭션만 롤백하고, 실패한 부분에 대해서만 다시 실행할 수 있습니다.
복수의 SavePoint를 정의할 수 있으며, 동일한 이름으로 SavePoint를 정의했을 때는 나중에 정의한 저장점이 유효합니다.
위 그림처럼, 저장점 A로 되돌리고 나서 다시 B와 같이 미래 방향으로는 되돌릴 수는 없습니다.
일단 특정 저장점까지 롤백되면 그 저장점 이후의 설정한 저장점이 무효가 되기 때문입니다.
즉, 'Rollback To A'를 실행한 시점에서 저장점 A 이후에 정의한 저장점 B는 존재하지 않습니다.
저장점 지정 없이 Rollback을 실행했을 경우에는 반영 안 된 모든 변경 사항을 취소하고 트랜잭션 시작 위치로 되돌아갑니다.
'JAVA' 카테고리의 다른 글
[JAVA] 컬렉션(Collection)[1]- List에 대하여 (0) | 2023.07.26 |
---|---|
[JAVA] 컬렉션(Collection)[0]- Collection에 대하여 (0) | 2023.07.26 |
FormData에 객체 배열(object[])을 담을 수 있는 방법 (0) | 2023.07.25 |
쿠키, 로컬 스토리지, 세션 스토리지 (0) | 2023.07.24 |
관계형 데이터베이스 설계(Schema / Entity , 1:1 / 1:M / N:M) (2) | 2023.07.23 |