트랜잭션(Transaction)은 데이터베이스에서 한 번에 수행되어야 하는 연산들의 모음을 의미합니다. 트랜잭션은 논리적인 작업 단위로 취급되며, 이 단위 내의 작업들이 모두 성공하거나, 모두 실패해야 합니다. 트랜잭션이 성공하면 해당 작업들이 영구히 저장되고, 실패하면 롤백되어 아무 일도 일어나지 않은 것처럼 처리됩니다.
트랜잭션은 ACID라고 불리는 4가지 중요한 특성을 갖습니다:
트랜잭션에 포함된 작업들은 모두 성공하거나 모두 실패해야 합니다. 하나라도 실패하면 트랜잭션 전체가 실패한 것으로 간주되며, 데이터베이스는 트랜잭션 실행 전 상태로 되돌아가게 됩니다.
예시: 은행 이체에서 한 계좌에서 돈을 출금하고 다른 계좌로 입금하는 두 작업이 있을 때, 둘 중 하나만 성공하면 데이터의 불일치가 발생하므로, 둘 다 성공하거나 둘 다 실패해야 합니다.
트랜잭션이 시작되기 전과 완료된 후에 데이터베이스는 일관성 있는 상태여야 합니다. 즉, 트랜잭션이 성공적으로 끝나면 모든 데이터는 비즈니스 규칙을 만족해야 하며, 데이터 무결성을 해치지 않아야 합니다.
예시: 특정 트랜잭션이 제약 조건을 위반하거나 데이터 무결성을 해치는 경우 트랜잭션은 실패해야 합니다.
여러 트랜잭션이 동시에 실행될 때, 각각의 트랜잭션은 독립적으로 실행되는 것처럼 보여야 합니다. 다른 트랜잭션이 완료되기 전에는 그 영향을 보지 않아야 합니다. 즉, 트랜잭션 간의 간섭을 방지하는 것입니다.
예시: 두 개의 트랜잭션이 동시에 같은 데이터를 수정하려고 할 때, 한 트랜잭션이 끝날 때까지 다른 트랜잭션은 그 수정된 데이터를 보지 못합니다.
트랜잭션이 성공적으로 완료되면 그 결과는 영구적으로 데이터베이스에 반영되어야 하며, 시스템 장애가 발생하더라도 트랜잭션이 성공한 상태는 보존되어야 합니다.
예시: 전원이 갑자기 나가거나 시스템이 충돌하더라도, 커밋된 트랜잭션의 결과는 손실되지 않습니다.
설명: 트랜잭션 내의 모든 작업이 성공적으로 수행되었음을 확인하고, 그 결과를 데이터베이스에 영구적으로 반영하는 명령입니다. COMMIT이 실행되면 트랜잭션이 완료되며, 그때까지의 모든 변경사항은 확정됩니다.
특징:
트랜잭션이 성공적으로 완료되었음을 의미.
데이터베이스에 영구적으로 변경사항이 반영됨.
트랜잭션이 종료되며, 다른 트랜잭션에서 그 결과를 볼 수 있게 됩니다.
예시: 은행 이체에서 출금과 입금이 모두 성공적으로 이루어진 경우, COMMIT을 실행하여 이체가 완료되었다는 사실을 데이터베이스에 반영합니다.
설명: 트랜잭션 내의 작업 중 하나라도 실패할 경우, 트랜잭션을 시작하기 전에 수행한 모든 작업을 취소하고, 데이터베이스를 이전 상태로 복구하는 명령입니다. 트랜잭션이 실패하거나 명시적으로 ROLLBACK이 호출되면, 그동안 수행된 모든 변경사항이 무효화됩니다.
특징:
트랜잭션이 실패했거나 중단되었음을 의미.
데이터베이스는 트랜잭션 시작 이전의 상태로 되돌아감.
트랜잭션 내에서 변경된 모든 데이터는 원래대로 복구됨.
예시: 은행 이체 중 출금은 성공했지만 입금이 실패한 경우, ROLLBACK을 실행하여 출금 작업을 취소하고, 데이터베이스를 트랜잭션 이전 상태로 되돌립니다.
트랜잭션 시작
트랜잭션이 시작되고 데이터베이스에 작업이 수행됩니다. 예를 들어, A 계좌에서 100원을 출금하고 B 계좌에 100원을 입금하는 작업을 트랜잭션으로 묶을 수 있습니다.
작업 수행
A 계좌에서 100원 출금
B 계좌에 100원 입금
성공 시: COMMIT
두 작업이 모두 성공하면, COMMIT을 실행하여 변경 사항을 영구히 데이터베이스에 반영합니다.
실패 시: ROLLBACK
만약 중간에 입금 작업이 실패했다면, ROLLBACK을 실행하여 출금 작업도 취소하고 트랜잭션 이전 상태로 되돌립니다.
이처럼 COMMIT과 ROLLBACK은 트랜잭션의 성공 또는 실패 여부에 따라 데이터베이스의 상태를 결정하는 중요한 역할을 합니다.
답: 트랜잭션 격리 수준이 낮아지면 주로 Isolation (격리성)이 영향을 받습니다. 트랜잭션 간의 독립성이 약해지면서 Dirty Read, Non-repeatable Read, Phantom Read와 같은 문제가 발생할 수 있습니다. 격리성이 낮을수록 트랜잭션 간에 더 많은 간섭이 발생하게 되고, 이는 데이터의 일관성에 영향을 줄 수 있습니다. 예를 들어, READ UNCOMMITTED 수준에서는 트랜잭션이 커밋되지 않은 데이터를 읽을 수 있어 데이터 무결성을 해칠 수 있습니다.
답: 일반적으로 트랜잭션 내에서는 하나의 COMMIT만 사용해야 합니다. 만약 COMMIT을 여러 번 사용한다면, 첫 번째 COMMIT 이후에는 트랜잭션이 종료되며, 그 후의 작업은 새로운 트랜잭션으로 처리되어야 합니다. 한 번 커밋된 후에는 이전 트랜잭션의 변경 사항이 영구적으로 데이터베이스에 반영되기 때문에, 이후의 작업에 대해 더 이상 ROLLBACK할 수 없습니다. 트랜잭션 관리의 복잡성을 높이므로, 실무에서는 트랜잭션 내에서 COMMIT을 여러 번 사용하는 것을 피하는 것이 좋습니다.
답: 애플리케이션에서 트랜잭션 관리에 실패하면 여러 가지 심각한 문제가 발생할 수 있습니다:
데이터 무결성 문제: 트랜잭션이 부분적으로만 성공하고 중간에 실패하면 데이터의 일관성이 깨질 수 있습니다. 예를 들어, 은행 이체에서 출금은 되었지만 입금이 이루어지지 않는 경우가 발생할 수 있습니다.
데이터 손실: 트랜잭션이 커밋되기 전에 실패하거나 ROLLBACK이 제대로 처리되지 않으면 데이터가 손실될 수 있습니다. 이로 인해 시스템에 큰 혼란이 생길 수 있습니다.
데이터 불일치: 여러 트랜잭션이 동시에 실행되면서 서로 간섭할 경우 데이터 불일치가 발생할 수 있습니다. 트랜잭션이 제대로 격리되지 않으면 하나의 트랜잭션이 다른 트랜잭션의 미완료 데이터를 읽어 잘못된 결과를 도출할 수 있습니다.
교착 상태 (Deadlock): 트랜잭션이 서로 잠금 자원을 대기하는 상황에서 교착 상태에 빠질 수 있으며, 시스템 전체가 멈추는 결과를 초래할 수 있습니다.
따라서 애플리케이션에서 트랜잭션 관리를 적절하게 하지 않으면 데이터베이스 시스템의 신뢰성 및 데이터 무결성에 큰 영향을 미칠 수 있습니다.