2. 핵심 원리
2.1 트랜잭션이란
트랜잭션은 "전부 반영되거나 전부 취소되는" 문장 묶음입니다. 이 성질을 원자성이라고 하고, 확정한 결과는 사라지지 않는 것을 지속성이라고 합니다. 다른 세션에 언제 얼마나 보이는지는 격리 수준이 정합니다(2.5).
| 명령 | 뜻 |
|---|---|
| COMMIT | 지금까지의 변경을 확정, 트랜잭션 끝 |
| ROLLBACK | 지금까지의 변경을 취소, 트랜잭션 끝 |
| SAVEPOINT 이름 | 중간 표식, 일부만 되돌리는 데 사용 |
2.2 시작과 자동 커밋
트랜잭션이 어떻게 시작되는지, 자동 커밋이 기본으로 켜져 있는지가 DB마다 다릅니다.
| 항목 | Oracle · Tibero | MySQL | MSSQL |
|---|---|---|---|
| 시작 | 첫 DML 에서 암묵 시작 | START TRANSACTION 또는 BEGIN | BEGIN TRAN |
| 자동 커밋 기본 | DB 에는 없음, 도구가 정함 | 켬 (autocommit=1) | 켬 (자동 커밋 모드) |
| 끝 | COMMIT, ROLLBACK | COMMIT, ROLLBACK | COMMIT TRAN, ROLLBACK TRAN |
Oracle 은 DB 자체에 자동 커밋이 없고 클라이언트 도구나 드라이버가 정합니다. SQL*Plus 는 기본이 꺼져 있고 JDBC 는 기본이 켜져 있습니다. 같은 Oracle 인데 도구에 따라 결과가 달라지는 이유입니다.
자동 커밋이 켜져 있으면 문장 하나가 끝날 때마다 커밋되어 ROLLBACK 이 되돌릴 것이 없습니다. 여러 문장을 묶으려면 MySQL 은 START TRANSACTION, MSSQL 은 BEGIN TRAN 으로 시작해 자동 커밋을 잠시 멈춥니다. MSSQL 의 IMPLICIT_TRANSACTIONS 옵션을 켜면 Oracle 처럼 첫 DML 에서 자동으로 시작합니다. 기본은 꺼져 있습니다.
핵심자동 커밋이 켜져 있으면 ROLLBACK 이 소용없습니다. 여러 문장을 묶으려면 트랜잭션을 명시적으로 시작하거나 자동 커밋을 끕니다.
2.3 문장이 실패하면
세 DB 모두 기본은 실패한 문장 하나만 취소되고 트랜잭션은 열려 있습니다. 앞에서 성공한 문장은 그대로 남아 있어서 애플리케이션이 오류를 보고 ROLLBACK 해야 합니다.
MSSQL 은 SET XACT_ABORT ON 이면 대부분의 오류에서 트랜잭션 전체가 롤백됩니다. 켜 두는 것이 안전한 경우가 많지만 모든 오류가 대상은 아니므로 오류 처리를 대신하지는 않습니다.
2.4 SAVEPOINT
SAVEPOINT 는 트랜잭션 안의 중간 표식입니다. 표식 이후만 되돌리고 앞부분과 트랜잭션은 유지합니다. 표식으로 되돌려도 트랜잭션은 끝나지 않아서 마지막에 COMMIT 이나 ROLLBACK 이 필요합니다.
| 동작 | Oracle · Tibero · MySQL | MSSQL |
|---|---|---|
| 표식 만들기 | SAVEPOINT s | SAVE TRAN s |
| 표식까지 되돌리기 | ROLLBACK TO [SAVEPOINT] s | ROLLBACK TRAN s |
표식보다 뒤에 만든 표식은 그 표식으로 되돌리면 함께 사라집니다. 그래서 sp1 로 되돌린 뒤에는 sp2 로 되돌릴 수 없습니다. H2 는 이 경우 오류 없이 지나가서 소스에는 넣지 않았습니다.
2.5 격리 수준
격리 수준은 동시에 실행되는 다른 트랜잭션의 변경이 내게 언제 보이는지를 정합니다. 표준은 네 단계입니다.
| 수준 | 커밋 전 값 읽기 | 같은 행을 다시 읽을 때 다른 값 |
|---|---|---|
| READ UNCOMMITTED | 읽힘(더티 리드) | 가능 |
| READ COMMITTED | 안 읽힘 | 가능 |
| REPEATABLE READ | 안 읽힘 | 안 나옴 |
| SERIALIZABLE | 안 읽힘 | 안 나옴, 순차 실행처럼 |
DB별 기본값은 다릅니다. 아래 표의 이름은 표준 표기입니다.
| DB | 기본 격리 수준 | 비고 |
|---|---|---|
| Oracle · Tibero | READ COMMITTED | Oracle 은 READ COMMITTED 와 SERIALIZABLE 만 |
| MySQL InnoDB | REPEATABLE READ | 표준 4단계 모두 |
| MSSQL | READ COMMITTED | 기본은 잠금 기반 |
Oracle 은 읽기를 언두로 일관성 있게 처리해서 읽기가 쓰기를 막지 않습니다. READ UNCOMMITTED 는 Oracle 에 없고, MSSQL 의 WITH (NOLOCK) 은 READ UNCOMMITTED 와 같은 효과입니다. MSSQL 은 기본이 잠금 기반이라 읽기와 쓰기가 서로 기다릴 수 있고, READ_COMMITTED_SNAPSHOT 옵션을 켜면 버전 기반이 됩니다.
주의커밋하지 않은 채 세션을 오래 두면 그 트랜잭션이 잡은 잠금이 유지되어 다른 세션이 기다립니다. 락 대기와 데드락 상세는 대용량·배치 카테고리에서 다룹니다.