https://wikidocs.net/4096
COMMIT
- 모든 작업을 정상적으로 처리하겠다고 확정하는 명령어이다.
- 트랜젝션의 처리 과정을 데이터베이스에 반영하기 위해서, 변경된 내용을 모두 영구 저장한다.
- COMMIT 수행하면, 하나의 트랜젝션 과정을 종료하게 된다.
- TRANSACTION(INSERT, UPDATE, DELETE)작업 내용을 실제 DB에 저장한다.
- 모든 사용자가 변경한 데이터의 결과를 볼 수 있다.
- ROLLBACK
- 작업 중 문제가 발생했을 때, 트랜젝션의 처리 과정에서 발생한 변경 사항을 취소하고, 트랜젝션 과정을 종료시킨다.
- 트랜젝션으로 인한 하나의 묶음 처리가 시작되기 이전의 상태로 되돌린다.
- TRANSACTION(INSERT, UPDATE, DELETE)작업 내용을 취소한다.
- 이전 COMMIT한 곳까지만 복구한다.
- 트랜젝션 작업 중 하나라도 문제가 발생하면, 모든 작업을 취소해야 하기 때문에 하나의 논리적인 작업 단위로 구성해 놓아야 한다.
- 문제가 발생하면, 논리적인 작업의 단위를 모두 취소해 버리면 되기 때문이다.
- COMMIT 명령어와 ROLLBACK 명령어의 장점
- 데이터 무결성이 보장된다.
- 영구적으로 변경하기 전에 데이터의 변경사항을 확인할 수 있다.
- 논리적으로 연관된 작업을 그룹화할 수 있다.
- 자동 COMMIT되는 경우
- SQL*PLUS가 정상 종료된 경우
- DDL과 DCL 명령문이 수행된 경우
- 자동 ROLLBACK되는 경우
- SQL*PLUS가 비정상 종료된 경우
- 정전이 발생했거나 컴퓨터 DOWN된 경우
ACID
ACID는 데이터베이스 내에서 일어나는 하나의 트랜잭션(transaction)의 안전성을 보장하기 위해 필요한 성질이다.
- Atomicity (원자성)
- Consistency (일관성)
- Isolation (격리성, 고립성)
- Durability (지속성
Atomicity(원자성)
트랜잭션이 안전성 보장을 위해 가져야 할 성질 중의 하나이다.
원자성은 시스템에서 한 트랜잭션의 연산들이 모두 성공하거나, 반대로 전부 실패되는 성질을 말한다.
원자성은 작업이 모두 반영되거나 모두 반영되지 않음으로서 결과를 예측할 수 있어야 한다.
- 하나의 단위로 묶여있는 여러 작업이 부분적으로 실행된다면, 업데이트가 일어났지만 누가 업데이트했는지 모르거나, 업데이트 날짜가 누락되는 등 데이터가 오염될 수 있다.
- 예를 들어 계좌이체를 할 때에는 다음과 같은 두 단계가 있다.
- A 계좌에서 출금한다.
- B 계좌에 입금한다.
- 계좌이체를 하려는데 A 계좌에서는 출금이 이뤄지고, B 계좌에 입금되지 않았다고 가정한다.
- 어디서 문제가 발생했는지 파악할 수 없다면, A 계좌에서 출금된 돈은 세상에서 사라지는 돈이 된다.
- 만약 은행에서 이런 일이 발생한다면, 은행은 더이상 제 기능을 할 수 없을 것이다다.
- A 계좌에서 출금하는 일에 성공했지만, B 계좌에 입금하는 작업에 실패한다면 계좌 A에서 출금하는 작업을 포함하여 모든 작업이 실패로 돌아가야 한다는 것이 Atomicity(원자성)이다.
- 원자성을 지켰다면 1번과 2번, 두 작업이 모두 성공적으로 완료되어야 한다.
- 그렇지 않으면(둘 중 하나의 작업이라도 실패한다면), 하나의 단위로 묶여있는 모든 작업이 실패하게 만들어 기존 데이터를 보호한다. (롤백 시킨다.)
- SQL에서도 마찬가지이다.
- 특정 쿼리를 실행했는데 부분적으로 실패하는 부분이 있다면, 전부 실패하도록 구현되어 있다.
- 때때로 충돌 요인에 대해서 선택지를 제공한다.
Consistency(일관성)
일관성은 데이터베이스의 상태가 일관되어야 한다는 성질이다.
일관성은 하나의 트랜잭션 이전과 이후, 데이터베이스의 상태는 이전과 같이 유효해야 한다.
다시 말해, 트랜잭션이 일어난 이후의 데이터베이스는 데이터베이스의 제약이나 규칙을 만족해야 한다는 뜻이다.
- 예를 들어 ‘모든 고객은 반드시 이름을 가지고 있어야 한다’는 데이터베이스의 제약이 있다고 가정한다.
- 다음과 같은 트랜잭션은 Consistency(일관성)를 위반한다.
- 이름 없는 새로운 고객을 추가하는 쿼리
- 기존 고객의 이름을 삭제하는 쿼리
- 데이터베이스의 유효한 상태는 다를수 있지만, 데이터의 상태에 대한 일관성은 변하지 않아야 한다.
- 이 예시는 ‘이름이 있어야 한다’ 라는 제약을 위반한다.
- 따라서 예시 트랜잭션이 일어난 이후의 데이터베이스는 일관되지 않는 상태를 가지게 된다.
❗️Isolation(격리성, 고립성)
격리성은 모든 트랜잭션은 다른 트랜잭션으로부터 독립되어야 한다는 뜻이다.
실제로 동시에 여러 개의 트랜잭션들이 수행될 때, 각 트랜젝션은 고립(격리)되어 있어 연속으로 실행된 것과 동일한 결과를 나타낸다.
- 예를 들어 게좌에 만 원이 있다고 가정한다.
- 이 계좌로부터 계좌 B로 6천 원을, 계좌 C로 6천 원을 동시에 계좌 이체하는 경우, 계좌 B에 먼저 송금한 뒤 계좌 C에 보내는 결과와 동일해야 한다.
- 동시에 트랜잭션을 실행한다고 해서 계좌 B와 C에 각각 6천 원씩 송금하여 마이너스 통장이 되는 것이 아니다.
- 각각의 송금 작업을 연속으로 실행하는 것과 동일한 결과가 나타나야 한다.
- 격리성을 지키는 각 트랜젝션은 철저히 독립적이기 때문에, 다른 트랜젝션의 작업 내용을 알 수 없다.
- 그리고 트랜잭션이 동시에 실행될 때와 연속으로 실행될 때의 데이터베이스 상태가 동일해야 한다.
Durability(지속성)
지속성은 하나의 트랜잭션이 성공적으로 수행되었다면, 해당 트랜잭션에 대한 로그가 남아야하는 성질을 말한다.
만약 런타임 오류나 시스템 오류가 발생하더라도, 해당 기록은 영구적이어야 한다는 뜻이다.
- 예를 들어 은행에서 게좌이체를 성공적으로 실행한 뒤에, 해당 은행 데이터베이스에 오류가 발생해 종료되더라도 계좌이체 내역은 기록으로 남아야 한다.
- 마찬가지로 계좌이체를 로그로 기록하기 전에 시스템 오류 등에 의해 종료가 된다면, 해당 이체 내역은 실패로 돌아가고 각 계좌들은 계좌이체 이전 상태들로 돌아가게 된다.
트랜잭션 격리수준
트랜잭션의 특징 ACID 중 Isolation에 따라, 트랜잭션간에 격리성(독립성)을 완전히 보장해야 한다.
하지만 그럴 경우를 완전히 보장하기 위해서는 모든 트랜잭션을 차례로 처리 해야 하고, 이는 성능의 하락으로 이어진다.
트랜잭션 격리 수준은, 동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것이다.
0 : READ UNCOMMITTED (커밋되지 않은 읽기)
- 각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있습니다.
- 정합성에 문제가 많은 격리 수준이기 때문에 사용하지 않는 것을 권장합니다.
- DIRTY READ 발생DIRTY READ
트랜잭션이 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 현상
💡 예시
트랜잭션 A 가 실행되고 update 됐을 때 그 사이에 트랜잭션 B가 실행된다.
그러면 트랜잭션 A에서 커밋이 되지 않았음에도 불구하고, 트랜잭션 B에서 트랜잭션 A가 update한 내용을 확인할 수 있게 된다.
1 : READ COMMITTED (커밋된 읽기)
- COMMIT 이 된 데이터만 읽습니다.
- RDB에서 대부분 기본적으로 사용되고 있는 격리 수준
- Dirty Read와 같은 현상은 발생하지 않지만 NON-REPEATABLE READ 발생
- NON-REPEATABLE READ
하나의 트랜잭션 내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 REPEATABLE READ 정합성에 어긋나는 것
💡 예시
트랜잭션 A에서 update 된 내용이 타 트랜잭션에서 바로 보여지지는 않는다. 근데 트랜잭션 A에서 커밋이 완료되었는데 트랜잭션 B에는 아직 완료되지 않은 경우, 트랜잭션 B에서 다시 한번 조회를 하게 된다면 update 된 상태가 조회가 된다
같은 조회(셀렉트)문인데도 결과가 다르기 때문에 정합성에 어긋난다. - 실제 테이블 값을 가져오는 것이 아니라 Undo 영역에 백업된 레코드에서 값을 가져온다.
- UNDO 영역:
간단하게 데이터를 저장하는 버퍼 기능을 한다고 보면 되고, 트랜잭션에서 연산(커밋 롤백)이 이루어지지 않아도 질의문에 의해 수정이 생기면 수정되기 이전 값이 저장되는 영역
2 : REPEATABLE READ (반복 가능한 읽기)
- 자신의 트랜잭션이 생성되기 이전의 트랜잭션에서 COMMIT 이 된 데이터만 읽습니다.
- MySQL과 MariaDB 가 기본으로 사용하는 격리 수준
- MySQL에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게 된다.PHANTOM READ
다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상
💡 예시
같은 테이블에 접근하는 여러개의 트랜잭션을 처리하고 있다. 그중 한 트랜잭션이 SELETE ~~ FOR UPDATE 을 사용하여 쓰기 잠금을 걸고 싶다고 가정한다. 쿼리문에 따라, SELECT하려는 레코드에 쓰기 잠금을 걸어야 하는데, Undo 레코드에는 잠금을 걸 수 없다. 따라서 위와 같은 쿼리는 Undo 영역의 변경 전 데이터를 가져오는 것이 아니라 현재 레코드의 값을 가져오게 된다. 따라서 레코드가 보였다 안보였다 한다고 해서 🎭 PHANTOM 이라고 한다.
REPEATABLE READ 추가 설명
모든 트랜젝션은 번호를 갖고, undo영역에서는 트랜잭션 번호를 함께 보관한다.
아까와 같이 트랜잭션 A와 트랜잭션 B가 있습니다. 트랜잭션 A의 번호는 13번이고 트랜잭션 B의 번호는 10번이다.
트랜잭션 B가 시작했다.
➡ 트랜잭션 A에서는 일부 값을 업데이트 하고 커밋하였다.
➡ 트랜잭션 B 안에서 실행되는 모든 SELECT 쿼리는 자신의 트랜잭션인 10번 보다 작은 트랜잭션 번호에서 변경한 것만 보게 된다. 즉, 번호가 13인 트랜잭션 A에서 변경한 내용은 10번인 트랜잭션 B에 영향을 주지 않는다. 이는 Undo 영역에 트랜잭션 번호가 저장되어있기 때문에 가능한 것이다.
3 : SERIALIZABLE (직렬화 가능)
- 가장 단순한 격리 수준이지만 가장 엄격한 격리 수준
- 데이터를 접근할 때, 항상 Lock을 걸고 데이터를 조회
- SERIALIZABLE에서는 PHANTOM READ가 발생하지 않는다.
- 성능 문제로 데이터베이스에서 거의 사용되지 않는다.
트랜잭션 문제들 한눈에 정리
(+) 트랜잭션 격리 수준에 따른 동시성과 일관성 변화
격리 수준이 높아지면서 데이터의 일관성이 유지될 수 있지만, 동시에 처리가능한 트랜잭션의 양은 떨어집니다. 격리수준이 낮아지면 일관성은 유지되기 어렵지만, 동시에 처리할 수 있는 트랜잭션의 양은 늘어나게 됩니다.
- 동시성 : 동시에 수행하는 트랜잭션 양
- 일관성 : 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것
위 블로그에서 commit, rollback 참조.
위 블로그에서 ACID 참조
위 블로그에서 격리수준 참조
'외부 활동 > JSCODE 데이터베이스 면접' 카테고리의 다른 글
JSCODE 데이터베이스 회고 (1) | 2023.12.08 |
---|---|
5주차 면접 예상질문 (0) | 2023.12.06 |
4주차 면접예상 질문 (0) | 2023.11.28 |
4주차 이상 현상, 정규화 (1) | 2023.11.28 |
3주차 면접 예상 질문 (0) | 2023.11.20 |