# Understand Transaction and Control in Database

---

**Contents**

**1️⃣** 트랜잭션 이해하기(Understand Transaction)  
**2️⃣** 트랜잭션 제어하기(Control Transaction)

---

## **1️⃣** 트랜잭션 이해하기(Understand Transaction)

**<mark>💡Keyword: 원자성(Atomicity), 일관성(Consistency), 격리성(Isolation), 영속성(Durability), 트랜잭션의 시작과 종료, 언두 데이터 세그먼트(Undo Data Segments), 버퍼 캐시(Buffer Cache), V$TRANSACTION</mark>**

### 트랜잭션 - 정의 (Definition of Transaction) **⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729817895364/57535ef9-7408-430e-88d5-0a1228299c58.png align="center")

**<mark>💡요약:</mark>** 트랜잭션은 데이터베이스에서 여러 작업을 하나의 단위로 묶어, **ALL or NOTHING** (모두 성공하거나 아무 것도 적용되지 않음) 방식으로 처리하는 기능이다. 이 방식은 작업 중 일부가 실패했을 때, 데이터 불일치를 방지할 수 있도록 도와준다.

1,000,000원을 **계좌 이체**하는 상황을 예로 설명하는 위의 예제를 살펴보자.

* 하나의 명령어는 \*\*저축 계좌(savings\_accounts)\*\*에서 1,000,000원을 빼는 것(출금)을 나타낸다.
    
* 다른 명령어는 \*\*당좌 계좌(checking\_accounts)\*\*에 1,000,000원을 더하는 것(입금)을 나타낸다.
    

이 두 명령어는 트랜잭션으로 묶여서 동시에 성공해야만 한다. 만약 한쪽 명령어가 실패하면, 다른 쪽도 취소되어야 하므로 출금이나 입금이 모두 실행되지 않게 된다. 이 방식은 작업 중 일부가 실패했을 때, 데이터 불일치를 방지할 수 있도록 도와준다.

---

### 트랜잭션 - 예 (Example of Transaction)**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729818568702/045d9991-20bf-432e-8f8a-a08e09c8806e.png align="center")

* **SET TRANSACTION NAME**: 트랜잭션의 이름을 지정하는 명령어이다. 여기서는 'bal\_update'라는 이름으로 트랜잭션을 시작하고 있다.
    
* **UPDATE**: 각 계좌에서 잔액을 업데이트하는 명령어이다. \*\*저축 계좌(savings\_accounts)\*\*에서 1,000,000원을 빼고, \*\*당좌 계좌(checking\_accounts)\*\*에 1,000,000원을 더하는 작업을 수행한다.
    
* **COMMIT**: 트랜잭션이 성공적으로 완료되었을 때, 이 명령어를 통해 모든 변경 사항을 최종적으로 데이터베이스에 적용한다.
    
    * 트랜잭션에서 중요한 점은 **COMMIT** 전에 문제가 발생하면 모든 변경 사항이 취소된다는 것이다. 즉, 잔액이 한 계좌에서 빠졌지만 다른 계좌에 들어가지 않은 상황은 발생하지 않게된다.
        

✅`COMMIT` 트랜잭션이 성공적으로 완료되면 **COMMIT**을 통해 데이터를 영구적으로 저장한다. 트랜잭션이 실패할 경우에는 모든 작업이 원래 상태로 돌아가게 된다. 이 과정에선 데이터가 바로 디스크에 쓰여지지 않고, 메모리의 한 부분인 \*\*버퍼 캐시(Buffer Cache)\*\*라는 임시 저장소를 거치게 된다. 참고로 메모리라서 빠르게 읽고 쓸 수 있기 때문에 성능을 높이기 위한 중요한 공간이다. 또한 트랜잭션에서 **COMMIT**을 사용하는 이유 중 하나가 바로 **디스크 I/O**를 효율적으로 관리하기 위함이다. 디스크 I/O는 데이터를 디스크에 읽고 쓰는 작업을 말하는데, 이 작업은 시간이 많이 걸리고 시스템 성능에도 영향을 미친다. 그래서 매번 데이터를 디스크에 쓰기보다는, 여러 변경 사항을 한 번에 처리하는 것이 더 효율적이다.

요약하자면 데이터를 매번 디스크에 쓰는 대신, 일단 메모리의 \*\*버퍼 캐시(Buffer Cache)\*\*에 임시로 저장해두고, 여러 작업이 끝난 후에 한 번에 **COMMIT**을 통해 디스크에 저장한다. 이를 통해 디스크 I/O 작업을 줄일 수 있게 되는 것이다. 만약 데이터 업데이트를 여러 번 시도하는데, 최종 결과가 바뀌지 않으면 변경된 내용을 디스크에 쓰는 것은 낭비라는 점도 생각해 볼만한 관점이다.

---

### 트랜잭션 - 트랜잭션이 동작하는 과정 (How transaction process)**⬇️**

**<mark>💡요약:</mark>** 아래의 이미지는 **계좌이체 트랜잭션의 예**를 통해 트랜잭션이 어떻게 동작하는지 보여준다. 트랜잭션은 데이터베이스에서 안전하게 데이터를 조회하거나 변경하는 과정을 설명하는데, 이때 **데이터베이스 서버(Database Server)**, **데이터파일(Data File)**, \*\*로그파일(Log File)\*\*이 각각 중요한 역할을 한다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729818558935/ef74a831-f694-41d0-8a9b-2dcc4121a437.png align="center")

**간단한 예제: A 사용자가 B 계좌로 1,000,000원을 이체하는 과정**

1. A 사용자가 데이터베이스 서버에 **변경** 요청을 보낸다.
    
2. 데이터베이스 서버는 A와 B 계좌의 데이터를 **데이터파일**에서 읽어와 **버퍼 캐시**에 저장한다.
    
3. 트랜잭션 중 데이터 변경 사항은 **로그파일**에 기록된다.
    
4. 트랜잭션이 성공적으로 완료되면, 데이터는 **데이터파일**에 저장되고, A 계좌에서 B 계좌로 1,000,000원이 이체된다.
    
5. 사용자는 이체가 완료되었다는 **결과**를 받는다.
    

* **조회/변경 (Read/Write)**: 사용자가 **조회** 요청을 하면, 데이터베이스는 데이터를 읽어와 결과를 사용자에게 반환한다. **변경** 요청의 경우, 사용자는 데이터를 업데이트하거나 삭제하는 작업을 수행한다. \*\*조회(Read)\*\*와 **변경(Write)** 상황에 따라 **트랜잭션 처리 과정**은 달라진다. 더자세한 설명은 아래 참조
    
* **데이터 읽기 (Data Read)**: 요청된 데이터는 \*\*디스크(Disk)\*\*에 저장되어 있고, 데이터베이스는 디스크에서 데이터를 읽어와 \*\*버퍼 캐시(Buffer Cache)\*\*에 저장한다. 이때, **버퍼 캐시**는 메모리에 존재하는 임시 저장소로서 데이터를 빠르게 처리할 수 있게 도와준다.
    
* **로그 기록 (Log)**: 트랜잭션 중 발생한 모든 작업은 \*\*로그파일(Log File)\*\*에 기록된다. 트랜잭션이 실패했을 경우 이 로그를 통해 데이터를 복구할 수 있게 된다.
    
* **데이터 쓰기 (Data Write)**: 트랜잭션이 성공적으로 끝나면, 버퍼 캐시에 있던 데이터가 **디스크**의 \*\*데이터파일(Data File)\*\*에 최종적으로 저장된다. 이는 데이터를 영구적으로 저장하는 작업이다.
    
* **결과 (Result)**: 트랜잭션이 성공적으로 처리된 후, 결과가 사용자에게 반환된다.
    

### 각 구성 요소의 역할

* **데이터베이스 서버(Database Server)**: 트랜잭션의 전체 과정을 관리하는 중심 역할을 한다. 사용자가 요청한 데이터 작업을 처리하며, 데이터를 **버퍼 캐시**에 저장하고 결과를 사용자에게 반환한다.
    
* **데이터파일(Data File)**: 변경된 데이터를 영구적으로 저장하는 장소이다. 최종적으로 트랜잭션이 완료되면, 데이터가 데이터파일에 기록된다.
    
* **로그파일(Log File)**: 트랜잭션 중 일어난 모든 데이터 변경 사항을 기록하는 곳이다. 이는 시스템 장애가 발생했을 때, 데이터를 복구하는 데 중요한 역할을 한다. \*\*검사점(Checkpoint)\*\*을 통해 현재까지의 작업이 완료되었는지 확인할 수 있다.
    
* **Checkpoint**: \*\*로그파일(Log File)\*\*과 **데이터파일(Data File)** 간의 \*\*동기화(Synchronization)\*\*를 맞추기 위해 사용되며, 트랜잭션이 진행된 후 주기적으로 변경된 데이터를 버퍼 캐시에서 데이터파일로 기록하는 역할을 한다. 이를 통해 복구 시 로그파일을 모두 읽어들이는 시간을 줄여 복구 속도를 높이고, 시스템 성능을 최적화하는 데 중요한 역할을 한다.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730002544174/1fce81eb-7383-4def-8f72-fadcde632fce.png align="center")

### 1\. **조회 (Read)**

**조회**는 데이터를 읽어오는 작업이다. 조회는 단순히 데이터를 읽어오는 작업이기 때문에 디스크에 데이터를 쓰거나 **COMMIT** 단계가 필요없다. 또한, 로그파일에 기록할 필요가 없다.

**조회 과정**:

1. **사용자 요청**: 사용자가 데이터 조회 요청을 보낸다. 예를 들어, 특정 사용자의 계좌 잔액을 조회하는 요청을 할 수 있다.
    
2. **데이터 읽기(Data Read)**: 데이터베이스 서버는 \*\*데이터파일(Data File)\*\*에서 해당 데이터를 \*\*버퍼 캐시(Buffer Cache)\*\*로 읽어온다. 만약 해당 데이터가 이미 버퍼 캐시에 존재한다면, 바로 캐시에서 데이터를 불러온다.
    
3. **결과 반환(Result)**: 데이터베이스 서버가 데이터를 조회한 후, 사용자가 요청한 정보를 반환한다. 조회 작업은 데이터에 변화를 주지 않기 때문에 \*\*로그파일(Log File)\*\*에 기록되지는 않게 된다.
    
4. **종료**: 조회가 완료되면 트랜잭션은 끝나고 사용자는 결과를 받는다.
    

### 2\. **변경 (Write)**

변경 작업은 데이터를 실제로 수정하는 작업이므로, **로그파일**에 기록이 필요하고, 트랜잭션이 완료되면 **COMMIT**을 통해 데이터가 **데이터파일**에 저장된다. 변경 작업은 조회보다 복잡하고, 데이터 안전성을 보장하기 위한 추가 단계가 필요하다.

**변경 과정**:

1. **사용자 요청**: 사용자가 데이터 변경 요청을 보낸다. 예를 들어, A 계좌에서 B 계좌로 1,000,000원을 이체하는 요청을 할 수 있다.
    
2. **데이터 읽기(Data Read)**: 데이터베이스 서버가 데이터를 \*\*버퍼 캐시(Buffer Cache)\*\*로 읽어온다. 이때 필요한 데이터가 버퍼 캐시에 없다면, **데이터파일**에서 읽어온다.
    
3. **로그 기록(Log Write)**: 데이터베이스 서버는 변경된 데이터에 대한 정보를 \*\*로그파일(Log File)\*\*에 기록한다. 로그는 시스템 장애 발생 시 데이터를 복구하는 데 사용된다. 이 작업은 트랜잭션의 안전성을 위해 매우 중요하다.
    
4. **데이터 쓰기(Data Write)**: 트랜잭션이 완료되면, 버퍼 캐시에서 데이터를 \*\*데이터파일(Data File)\*\*에 영구적으로 저장한다. 이 과정은 일반적으로 **COMMIT** 명령어를 통해 이루어진다.
    
5. **결과 반환(Result)**: 데이터 변경이 성공적으로 완료된 후, 사용자는 변경된 결과를 받는다.
    

결론적으로, **조회**는 데이터를 읽어오는 과정만으로 끝나지만, **변경**은 데이터를 실제로 수정하고, 트랜잭션의 안정성을 위해 **로그 기록**과 **데이터 쓰기** 단계가 추가로 필요하다.

---

### 트랜잭션 처리과정 - 오라클 데이터베이스 아키텍쳐**⬇️**

**<mark>💡요약:</mark>** \*\*데이터베이스 버퍼 캐시(Database buffer Cache)\*\*는 데이터를 디스크로 쓰기 전에 메모리에서 임시 저장하여 성능을 최적화한다. \*\*리두 로그 버퍼(Redo log buffer)\*\*는 트랜잭션의 변경 사항을 저장하는 메모리 공간으로, 일정 시점마다 \*\*리두 로그 파일(Redo log file)\*\*에 기록된다. 이를 통해 트랜잭션 복구가 가능하다.

* \*\*온라인 리두 로그(Online Redo log)\*\*는 현재 진행 중인 트랜잭션의 변경 사항을 기록하며, \*\*아카이브 리두 로그(Archived Redo log)\*\*는 사용된 온라인 로그를 백업하여 장애 복구 시 사용할 수 있게 한다.
    
* \*\*플래시백 로그(Flashback Log)\*\*는 데이터베이스를 과거의 상태로 복구하는 데 사용된다.
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730003052743/45a9c4c9-6796-43b8-8443-a72daddfcc70.png align="center")

### 1\. **데이터베이스 버퍼 캐시(Database Buffer Cache)의 역할**

* **데이터베이스 버퍼 캐시**는 **메모리** 내에 위치한 공간으로, 디스크에서 읽어온 데이터를 임시로 저장하는 곳이다.
    
* 데이터베이스가 디스크에서 데이터를 읽어오거나, 트랜잭션에서 데이터를 변경할 때, 그 변경된 데이터는 먼저 **버퍼 캐시**에 저장된다.
    
* **역할**: 이를 통해 데이터베이스는 디스크 I/O를 줄여 성능을 향상시키고, 데이터가 나중에 디스크로 기록되기 전에 메모리 내에서 처리되도록 한다. 따라서 자주 사용되는 데이터를 빠르게 접근할 수 있게 해주는 중요한 역할을 한다.
    

### 2\. **리두 로그 버퍼(Redo Log Buffer)의 역할과 로그파일과의 관계**

* \*\*리두 로그 버퍼(Redo Log Buffer)\*\*는 **메모리**에 위치한 공간으로, 데이터베이스의 변경 사항을 기록하는 역할을 한다. 변경된 데이터는 먼저 버퍼에 저장된 후, 일정 시점이 되면 \*\*리두 로그 파일(Redo Log File)\*\*로 옮겨진다.
    
* **로그파일과의 관계**: 리두 로그 버퍼에 기록된 내용은 일정 시점마다 \*\*리두 로그파일(Redo Log Files)\*\*에 저장된다. 이는 시스템 장애 발생 시 데이터베이스가 **리두 로그파일**을 통해 변경된 데이터를 복구할 수 있도록 하기 위함이다. 리두 로그는 데이터를 영구적으로 복구하는 데 핵심적인 역할을 한다.
    

### 3\. **로그파일이 커질 경우를 대비한 3가지 로그**

* 데이터베이스에서 로그파일이 커질 경우 시스템 성능에 영향을 미칠 수 있다. 이를 관리하고 장애 복구 시 유용하게 사용하기 위해 세 가지 종류의 로그가 사용된다.
    

#### 3.1 **온라인 리두 로그(Online Redo Log)**

* **역할**: **온라인 리두 로그**는 현재 진행 중인 트랜잭션의 <mark>변경 사항을 기록</mark>하는 로그파일이다. 리두 로그 버퍼에 있는 내용이 주기적으로 이 파일에 저장된다.
    
* 트랜잭션이 발생하면, 온라인 리두 로그는 데이터를 기록하여 트랜잭션 완료 전에도 모든 변경 사항이 안전하게 저장될 수 있도록 한다.
    
* **특징**: 시스템 장애가 발생할 때, **온라인 리두 로그**는 가장 최근의 변경 사항을 포함하고 있어 이를 복구하는 데 중요한 역할을 한다.
    

#### 3.2 **아카이브 리두 로그(Archived Redo Log)**

* **역할**: **아카이브 리두 로그**는 다 사용된 온라인 리두 로그가 차면 <mark>자동으로 백업</mark>되는 로그파일이다.
    
* 이 로그는 시스템 장애 발생 시 데이터베이스가 **과거의 데이터 변경 기록**을 안전하게 복구할 수 있게 도와준다.
    
* **특징**: 아카이브 리두 로그는 오래된 로그 기록을 보관하여 트랜잭션의 이전 상태로 되돌릴 수 있는 복구 포인트를 제공한다.
    

#### 3.3 **플래시백 로그(Flashback Log)**

* **역할**: \*\*플래시백 로그(Flashback Log)\*\*는 데이터베이스가 <mark>과거 시점으로 되돌아갈 수</mark> 있도록 도와주는 로그이다.
    
* 이 로그는 데이터가 변경되기 이전의 상태를 기록해두고, **Flashback** 기능을 통해 사용자가 특정 시점으로 데이터베이스를 되돌릴 수 있게 해준다.
    
* **특징**: 플래시백 로그는 실수로 데이터를 잘못 수정하거나 삭제했을 때, 그 이전 상태로 복구하는 데 유용하다.
    

---

### 트랜잭션 처리과정 - 리두 로그 버퍼 (Redo Log Buffer/File)**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730010068850/02b96283-89a6-416b-99b7-def59fc7d4ac.png align="center")

* 리두 로그는 데이터베이스의 변경 사항을 기록하고, 이를 통해 데이터베이스를 장애 전 상태로 복원할 수 있게 도와주는 중요한 요소이다. **리두 로그 버퍼**는 메모리에서 임시로 데이터를 저장하고, **리두 로그 파일**은 이를 디스크에 저장하여 데이터를 안전하게 보존한다.
    
* **LGWR(Log Writer)** 메모리에 있는 로그 데이터를 디스크의 리두 로그 파일로 주기적으로 옮기는 역할을 한다.
    

### 간단한 예제:

1. **조회 작업**: A 사용자가 B 계좌의 잔액을 조회할 때, 데이터는 변경되지 않으므로 **리두 로그**에 기록되지 않는다.
    
2. **변경 작업**: A 사용자가 B 계좌로 1,000,000원을 이체할 때, A 계좌의 잔액 감소와 B 계좌의 잔액 증가가 **리두 로그 버퍼**에 기록되고, 이후 **리두 로그 파일**에 저장된다. 시스템 장애가 발생해도 이 로그를 통해 트랜잭션을 복구할 수 있게된다.
    

---

### 트랜잭션 특성 - ACID 특성**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729820460663/283cfcc8-9d06-47b0-906b-a9cffd165029.png align="center")

---

### 트랜잭션 특성 - 원자성(Atomicity)**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729820503570/cd6ddd70-5da8-4a30-9a5d-010d985c603d.png align="center")

### 원자성(Atomicity)의 정의

* **트랜잭션은 분리할 수 없는 하나의 단위**이다. 즉, 트랜잭션 내에서 수행되는 여러 작업은 개별적으로 수행될 수 없으며, 전체가 하나의 작업처럼 처리된다.
    
* **작업이 모두 수행되거나, 하나도 수행되지 않아야 함**: 트랜잭션의 모든 작업이 성공적으로 완료되지 않으면, 그 트랜잭션 내에서 이루어진 모든 작업은 취소되어야 한다. 이 과정을 \*\*롤백(Rollback)\*\*이라고 한다.
    

**✅예시:** 트랜잭션이 **100개의 데이터를 업데이트**하려고 시도했으나, **20개의 데이터가 업데이트된 후 시스템 장애**가 발생한 상황을 가정해보자

* 이 경우 트랜잭션은 원자성을 보장하기 때문에, 데이터베이스는 이미 변경된 20개의 데이터를 \*\*롤백(Rollback)\*\*하여 트랜잭션이 실행되기 전의 상태로 되돌려야 한다.
    

---

### 트랜잭션 특성 - 일관성(Consistency)**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729820529811/3c1bb36f-4270-4d05-b609-f3e44a9cd20e.png align="center")

### 일관성(Consistency)의 정의

* **트랜잭션에서 사용되는 모든 데이터는 일관되어야 함**: 트랜잭션이 시작되기 전에 데이터는 **일관된 상태**여야 하며, 트랜잭션이 끝난 후에도 데이터는 여전히 **일관성을 유지**해야 한다.
    
* **트랜잭션의 전후**: 트랜잭션이 실행되기 전과 실행된 후에 데이터베이스가 **무결한 상태**를 유지해야 한다. 즉, 트랜잭션이 완료된 후에도 데이터가 일관성을 유지해야 한다.
    

**✅예시:** 계좌 이체 트랜잭션에서 **한 계좌만** 처리하게 되면 데이터의 **일관성**이 깨지게 된다.

* 예를 들어, A 계좌에서 1,000,000원이 빠져나갔는데 B 계좌에 그 금액이 입금되지 않으면, 데이터의 일관성이 깨진 것이다. 트랜잭션은 이 문제를 해결해야 하며, 모든 변경 사항이 동시에 완료되거나 모두 취소되어야 일관성을 유지할 수 있게 된다.
    

---

### 트랜잭션 특성 - 격리성(Isolation)**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729820556012/8b9a8cb2-2089-4ecf-9107-943f1738a391.png align="center")

### 격리성(Isolation)의 정의

* **현재 트랜잭션이 접근하고 있는 데이터는 다른 트랜잭션으로부터 격리되어야 함**: 한 트랜잭션이 데이터를 변경하는 동안, 그 데이터를 다른 트랜잭션이 수정하거나 읽을 수 없다. 트랜잭션이 완료되기 전까지는 해당 트랜잭션의 중간 결과를 다른 트랜잭션이 보지 못한다.
    
* **트랜잭션이 완료되기까지 변경하는 데이터는 다른 트랜잭션에게 보여져서는 안 됨**: 트랜잭션이 완료되어야만 그 변경 사항이 다른 트랜잭션에게 공개되며, 트랜잭션 도중에는 서로 격리되어야 데이터의 무결성이 유지된다.
    

**✅예시:** : **hr.employee** 테이블을 업데이트하는 트랜잭션이 실행되는 동안, 다른 트랜잭션이 동일한 테이블에서 수정된 내용을 보지 못한다.

* 즉, 하나의 트랜잭션이 완료되기 전에는 다른 트랜잭션에게 그 결과가 노출되지 않으며, **사용자에게는 트랜잭션이 순서대로 실행되는 것처럼 보여야 한다.**
    

---

### 트랜잭션 특성 - 영속성(Durability)**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1729820576055/5485daf7-cc52-4f24-8eaf-ac9fab12e61e.png align="center")

### 영속성(Durability)의 정의

* **트랜잭션이 정상적으로 종료되면 그 결과는 시스템 오류가 발생하더라도 영구적으로 남아야 함**: 즉, 트랜잭션이 완료되고 \*\*커밋(Commit)\*\*이 되면, 그 결과는 시스템 장애나 오류가 발생해도 **데이터베이스에 안전하게 저장**된다.
    
* **혹시 완료된 데이터에 장애가 생기면 이를 다시 복구할 수 있어야 함**: 트랜잭션이 완료된 후 장애가 발생해도 데이터는 복구 가능해야 하며, 트랜잭션의 변경 사항은 **디스크**에 안전하게 저장되어야 한다.
    

**✅예시: 계좌 이체 트랜잭션**에서 데이터가 로그에 기록되고 \*\*커밋(Commit)\*\*이 된 후, 시스템 장애가 발생해도, 시스템이 다시 재가동되었을 때 해당 변경 사항은 **디스크**에 반영되어 있어야 한다. 즉 계좌 이체가 완료된 후 서버가 다운되더라도, 이체된 금액은 영구적으로 반영되어야 한다.

---

### 트랜잭션 구조 - 트랜잭션은 하나 또는 그 이상의 명령문으로 구성됨**⬇️**

**<mark>💡요약:</mark>** **트랜잭션**은 **하나 이상의 명령문**으로 구성될 수 있으며, 이 명령문들은 **데이터 조작문(DML)** 또는 \*\*데이터 정의문(DDL)\*\*으로 이루어진다. 각 명령문은 함께 실행되어 데이터베이스의 무결성과 일관성을 유지할 수 있도록 도와준다.

* **하나 또는 그 이상의 명령문**으로 트랜잭션이 구성될 수 있다. 트랜잭션은 여러 개의 작업을 하나의 단위로 묶어 처리하기 때문에, 모든 명령문이 함께 실행되어야 한다.
    
* 트랜잭션은 주로 **데이터 조작문(DML, Data Manipulation Language)** 또는 \*\*데이터 정의문(DDL, Data Definition Language)\*\*으로 이루어져 있다.
    

### 데이터 조작문 (DML, Data Manipulation Language)

* \*\*데이터 조작문(DML)\*\*은 **데이터를 조회, 추가, 수정, 삭제**하는 명령어들로 구성된다.
    
* **조회(Read)**: 데이터를 단순히 읽어오는 작업으로, DML의 `SELECT` 문을 사용한다.
    
* **변경(Write)**: 데이터에 변화를 주는 작업으로, `INSERT`(데이터 추가), `UPDATE`(데이터 수정), `DELETE`(데이터 삭제)와 같은 명령어가 포함된다.
    
* DML 명령문은 트랜잭션 안에서 여러 개가 함께 실행될 수 있으며, 모두 성공해야만 데이터베이스에 최종 적용된다.
    
* **DML 예시**:
    
    * A 사용자가 B 계좌의 잔액을 조회하는 경우: `SELECT balance FROM accounts WHERE account_id = B`
        
    * A 사용자가 B 계좌에 1,000,000원을 추가하는 경우: `UPDATE accounts SET balance = balance + 1000000 WHERE account_id = B`
        

---

### 데이터 정의문 (DDL, Data Definition Language)

* \*\*데이터 정의문(DDL)\*\*은 **데이터베이스 구조를 정의**하는 명령어들이다.
    
* 예를 들어, 새로운 테이블을 생성하거나, 기존 테이블을 수정 또는 삭제하는 작업을 포한다.
    
* DDL 명령문에는 `CREATE`(테이블 생성), `ALTER`(테이블 구조 변경), `DROP`(테이블 삭제) 등이 있다.
    
* DDL은 트랜잭션처럼 사용되며, 명령문이 성공적으로 완료되면 데이터베이스 구조가 바뀐다.
    
* **DDL 예시**:
    
    * 새로운 `employees` 테이블을 생성하는 경우: `CREATE TABLE employees (id INT, name VARCHAR(50), position VARCHAR(50))`
        
    * 기존 `employees` 테이블에 `salary` 컬럼을 추가하는 경우: `ALTER TABLE employees ADD salary INT`
        

---

### 트랜잭션 구조 - 트랜잭션의 시작**⬇️**

**<mark>💡요약</mark>**: **트랜잭션의 시작**에 대해 알아본다. 트랜잭션은 데이터베이스에서 여러 작업을 하나의 단위로 묶어 처리하는데, 그 시작 과정에서 몇 가지 중요한 단계가 있다. 좀 더 자세히 살펴보면 트랜잭션은 첫 SQL 문이 실행되면 자동으로 시작되며, 이 과정에서 데이터베이스는 트랜잭션을 추적하고 롤백할 수 있도록 **언두 데이터 세그먼트**를 확보한다. 또한, 트랜잭션에 고유한 **ID**가 부여되며, 이를 통해 트랜잭션 상태를 **V$TRANSACTION 뷰**에서 확인할 수 있게 된다.

* **첫 번째 SQL 문이 시작되면 트랜잭션이 자동으로 시작된다.**
    
    * 트랜잭션은 사용자가 처음으로 **SQL 문**(예: `SELECT`, `INSERT`, `UPDATE`, `DELETE`)을 실행하면 자동으로 시작된다. 특별히 트랜잭션을 시작하라는 명령을 내리지 않아도, 첫 SQL 문이 실행되면서 트랜잭션이 시작된다.
        
* 트랜잭션 안에서 **DML, DDL, SET TRANSACTION** 문을 사용할 수 있다.
    
    * 트랜잭션 안에서 사용할 수 있는 명령문은 **DML(Data Manipulation Language)**, **DDL(Data Definition Language)**, 그리고 트랜잭션의 특성을 설정할 수 있는 **SET TRANSACTION 문**이다.
        
    * DML은 데이터를 조회하거나 수정하는 데 사용되고, DDL은 데이터베이스 구조를 정의하거나 변경하는 데 사용된다.
        
* **언두 데이터 세그먼트(Undo Data Segments) 확보하여 롤백 지원**
    
    * 트랜잭션이 시작되면, 데이터베이스는 \*\*언두 데이터 세그먼트(Undo Data Segments)\*\*를 확보한다. 이는 트랜잭션이 완료되기 전에 데이터가 변경되었을 경우, 이전 상태로 되돌리기 위한 정보를 저장하는 공간이다.
        
    * 언두 세그먼트는 트랜잭션 도중 문제가 발생하면 \*\*롤백(Rollback)\*\*을 통해 데이터베이스를 트랜잭션 이전 상태로 복구할 수 있도록 도와다.
        
* **트랜잭션 ID 부여 후 정보 삽입**
    
    * 데이터베이스는 각 트랜잭션에 **고유한 트랜잭션 ID**를 부여하고, 이 ID와 관련된 정보를 **트랜잭션 테이블**에 저장하게 된다. 이 고유 ID는 트랜잭션을 추적하고 관리하는 데 사용된다.
        
* **V$TRANSACTION 뷰를 통해 트랜잭션 상태 확인 가능**
    
    * 데이터베이스는 **V$TRANSACTION 뷰**를 통해 현재 진행 중인 트랜잭션의 상태를 확인할 수 있게 한다. 이를 통해 사용자는 각 트랜잭션이 어떤 상태에 있는지(예: 진행 중, 커밋됨, 롤백됨)를 실시간으로 확인할 수 있다.
        

**간단한 예제:**

1. 사용자가 `UPDATE` 문을 실행하여 A 계좌의 잔액을 1,000,000원 감소시키는 경우
    
    * **트랜잭션 시작**: `UPDATE` 문이 처음 실행되면서 트랜잭션이 자동으로 시작된다.
        
    * **언두 데이터 세그먼트 확보**: A 계좌의 원래 잔액 정보가 언두 세그먼트에 저장되어, 필요 시 롤백이 가능하게 한다.
        
    * **트랜잭션 ID 생성**: 이 트랜잭션에 고유한 ID가 부여되고, 트랜잭션 테이블에 기록된다.
        
    * **상태 확인**: 사용자는 V$TRANSACTION 뷰를 통해 트랜잭션 상태를 확인할 수 있다.
        

**✅언두 데이터 세그먼트(Undo Data Segments): 언두 데이터 세그먼트**는 **트랜잭션이 변경한 데이터의 이전 상태**를 저장하는 공간이다. 만약 트랜잭션 도중 오류가 발생해 롤백이 필요할 때, 언두 데이터 세그먼트에 저장된 정보를 사용하여 데이터베이스를 트랜잭션 이전 상태로 복구할 수 있게 된다. 예를 들어, 계좌 이체 트랜잭션에서 A 계좌에서 돈이 빠져나간 후 트랜잭션이 중단되면, 언두 데이터 세그먼트를 사용하여 A 계좌의 잔액을 원래대로 되돌릴 수 있게 된다.

**✅언두 데이터 세그먼트(Undo Data Segments)와 버퍼 캐시(Buffer Cache)의 관계:** 언두 데이터 세그먼트의 내용도 **버퍼 캐시**에 저장된다. 즉, 트랜잭션이 데이터를 변경하면 그 변경된 데이터와 함께 언두 데이터(이전 데이터)도 버퍼 캐시에 올라가게 된다. 이는 롤백 시 빠르게 데이터를 복구할 수 있도록 하기 위함이다. 또한 트랜잭션이 진행 중일 때, 버퍼 캐시에는 변경된 데이터뿐 아니라 **언두 데이터**도 함께 저장되어 있어야 한다. 이로 인해 트랜잭션이 도중에 실패하면, 버퍼 캐시의 언두 데이터를 활용해 데이터베이스를 트랜잭션 이전 상태로 되돌릴 수 있게 된다. 트랜잭션 중 문제가 발생하여 \*\*롤백(Rollback)\*\*이 필요할 때, 언두 데이터는 버퍼 캐시와 디스크의 언두 세그먼트에서 참조되어 데이터를 원래 상태로 복구할 수 있다.

**간단한 예제:**

1. A 사용자가 B 계좌로 1,000,000원을 이체하는 트랜잭션이 시작되면:
    
    * A 계좌의 잔액 감소와 B 계좌의 잔액 증가가 버퍼 캐시에 저장된다.
        
    * 동시에, A 계좌와 B 계좌의 잔액 원본 데이터가 언두 데이터 세그먼트에 저장되고, 이는 버퍼 캐시에도 올라간다.
        
2. 만약 트랜잭션 도중 오류가 발생하면:
    
    * 버퍼 캐시에 있는 언두 데이터가 사용되어, A와 B 계좌의 잔액이 원래대로 복구된다.
        

---

### 트랜잭션 구조 - 트랜잭션의 시작**⬇️**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730011664483/04c08f66-5d2d-4cad-9d91-080abfd7d1e6.png align="center")

* **테이블 생성 (Creating a Table)**:
    
    * `CREATE TABLE temp_table` 문을 통해 **temp\_table**이라는 이름의 테이블이 생성되었다. 이 테이블에는 **user\_id**(정수형)와 **user\_name**(문자열형) 두 개의 열(column)이 포함되어 있다.
        
    * 이 단계는 데이터베이스에 테이블 구조를 정의하는 **DDL(Data Definition Language)** 명령이다.
        
* **데이터 삽입 (Inserting Data)**:
    
    * `INSERT INTO temp_table VALUES (1000, '강하나');` 문을 통해 **temp\_table**에 **user\_id가 1000**이고 \*\*user\_name이 '강하나'\*\*인 행(row)을 삽입한다.
        
    * 이 단계는 **DML(Data Manipulation Language)** 명령이며, 데이터가 실제로 테이블에 추가된다.
        
    * 이 명령이 실행되면서 트랜잭션이 자동으로 시작된다.
        
* **트랜잭션 상태 확인 (Checking Transaction Status)**:
    
    * `SELECT * FROM V$TRANSACTION;` 명령을 통해 **현재 진행 중인 트랜잭션**의 상태를 확인한다.
        
    * **V$TRANSACTION 뷰**를 사용하여 트랜잭션의 고유 ID, 상태, 시작 시간 등을 확인할 수 있다. 여기서 `STATUS` 열에 **ACTIVE**라고 표시된 것은 이 트랜잭션이 아직 진행 중임을 의미한다.
        
* **커밋 (Commit)**:
    
    * `COMMIT;` 문을 실행하면 트랜잭션이 완료되며, 변경 사항이 데이터베이스에 **영구적으로 저장**된다.
        
    * 커밋이 완료되면 트랜잭션은 더 이상 **ACTIVE** 상태가 아니며, 다른 사용자에게도 데이터 변경 사항이 보이게 된다.
        

---

### 트랜잭션 구조 - 트랜잭션이 종료되는 경우#1**⬇️**

**<mark>💡요약:</mark>** 트랜잭션은 명시적으로 COMMIT 또는 ROLLBACK 명령어를 실행하거나, DDL 명령어를 사용해 데이터베이스 구조를 정의 또는 변경할 때 자동으로 종료된다. 이를 통해 트랜잭션의 상태를 명확하게 관리할 수 있게 된다.

* **명시적으로 COMMIT 또는 ROLLBACK 문을 실행시키는 경우**
    
    * 사용자가 직접 **COMMIT** 또는 **ROLLBACK** 명령을 실행하면, 트랜잭션이 종료된다.
        
    * **COMMIT**은 트랜잭션에서 이루어진 모든 변경 사항을 영구적으로 데이터베이스에 저장하며, **ROLLBACK**은 모든 변경 사항을 취소하고 원래 상태로 되돌린다.
        
* **DDL 명령어를 실행시키는 경우**
    
    * DDL(Data Definition Language) 명령어는 **데이터베이스 구조를 정의하거나 변경**하는 명령어로, 여기에는 `CREATE`, `DROP`, `RENAME`, `ALTER`와 같은 명령어가 포함된다.
        
    * DDL 명령어를 실행할 때마다 해당 명령어 전후로 **자동으로 COMMIT**이 실행되어 트랜잭션이 종료된다. 즉, DDL 명령어는 자동으로 트랜잭션을 종료시키는 역할을 한다.
        
    * 예를 들어, `CREATE TABLE` 명령을 사용해 테이블을 생성하면 그 명령어가 실행되기 전에 현재 트랜잭션이 자동으로 커밋되고, 명령이 완료된 후에도 자동으로 커밋된다.
        
    * 사용자가 SQL 도구(예: SQL Plus, SQL Developer 등)를 정상적으로 종료하면, 현재 트랜잭션도 **자동으로 COMMIT**될 수 있다. 프로그램에 따라 다를 수 있지만, 대부분의 도구에서 정상 종료 시 자동 커밋이 이루어진다.
        
    * 만약 비정상적으로 프로그램이 종료되면, 현재 트랜잭션은 **자동으로 ROLLBACK**된다.
        

---

## **2️⃣** 트랜잭션 제어하기(Control Transaction)

**<mark>💡Keyword: Commit, Rollback, Save Point, Concurrency Control, Lock</mark>**

**<mark>💡요약:</mark>** 트랜잭션 제어는 데이터베이스의 **일관성**을 보장하며, **데이터 수정**이 올바르게 수행될 수 있도록 돕는다.

**트랜잭션 제어**란 데이터베이스에서 **트랜잭션**(Transaction)을 관리하는 것을 의미한다.  
**트랜잭션**이란 데이터베이스에서 실행되는 **작업의 묶음**으로, 여러 **DML**(Data Manipulation Language) 문장이 포함된다. 트랜잭션 제어는 **데이터의 일관성**을 유지하기 위해 중요한 역할을 한다. 예를 들어, 은행에서 계좌 이체를 할 때, **송금**과 **입금** 과정이 둘 다 완료되어야 일관성이 유지된다. 트랜잭션 제어는 이러한 작업이 **완전히** 이루어졌는지 확인하고, **문제가 생기면 롤백**(rollback)하여 **원래 상태로 되돌리는** 기능도 포함한다.

---

### 트랜잭션 제어문(Transaction Control Statement)

**<mark>💡요약: </mark>** 트랜잭션 제어문은 데이터베이스의 변경 사항을 영구적으로 저장하거나, 오류가 발생했을 때 안전하게 이전 상태로 되돌리기 위한 도구로 COMMIT, ROLLBACK, ROLLBACK TO SAVEPOINT, SAVEPOINT 등이 제어문에 포함된다.  

* **COMMIT:** 현재 트랜잭션을 **종료하고 변경된 사항을 영구적으로 유지**(permanently save)한다. 이를 통해 데이터베이스에 **디스크로 반영**되어 수정된 데이터가 확정된다. **SAVEPOINT**(임시 저장 지점)를 제거하고, **LOCK**(잠금)을 해제한다.
    
    * 예: 은행에서 돈을 이체할 때, 이체가 끝난 후 **COMMIT**을 사용하면 송금이 완료된다.
        
* **ROLLBACK:** 현재 트랜잭션에서 이루어진 **모든 작업을 되돌린다.** (undo all changes). 문제가 발생했을 때, 트랜잭션을 원래 상태로 되돌리기 위해 사용된다.
    
    * 예: 은행 이체 중에 에러가 발생하면 **ROLLBACK**을 사용하여 모든 작업을 취소하고 처음 상태로 돌아간다.
        
* **ROLLBACK TO SAVEPOINT:** 마지막으로 설정한 **SAVEPOINT** 이후에 진행된 작업만 **되돌린다.**(undo changes after the last save point). 부분적으로 되돌릴 때 유용하다.
    
    * 예: 여러 단계의 데이터 수정 작업 중 오류가 발생하면, SAVEPOINT를 지정한 지점까지 되돌릴 수 있다.
        
* **SAVEPOINT:** 트랜잭션이 진행되는 중간에 **ROLLBACK할 지점을 저장**(set a temporary save point)한다. 트랜잭션 중 특정 지점까지 되돌릴 수 있도록 한다.
    
    * 예: 장바구니에 여러 물건을 추가하다가, 특정 지점(SAVEPOINT)을 설정해두고 이후에 되돌리고 싶을 때 사용한다.
        

---

### 트랜잭션 이름(Transaction Name)

**<mark>💡요약: </mark>** 트랜잭션 이름을 설정하면, 긴 트랜잭션을 쉽게 관리하고, 문제가 발생했을 때 빠르게 찾아 복구하는 데 도움이 된다. 간략한 특징으로는 **트랜잭션 이름**은 선택 사항이고 트랜잭션 종료 시 로그에 기록되어 나중에 쉽게 검색이 가능해진다.

`SET TRANSACTION ... NAME`

* **트랜잭션 명은 선택사항**이며, 필요할 때 특정 트랜잭션을 지정하기 위해 사용한다.
    
    * 예: 여러 작업 중 하나의 트랜잭션을 구분하고 싶다면, `SET TRANSACTION ... NAME` 명령어로 트랜잭션에 이름을 지정할 수 있다.
        
* **길게 수행되는 트랜잭션의 모니터링을 편하게** 한다. 이름을 지정하면 어떤 트랜잭션이 오래 걸리는지 파악하기 쉽다.
    
    * 예: 트랜잭션에 이름을 붙여두면, 어떤 작업이 느리게 진행되는지 쉽게 모니터링할 수 있게 된다.
        
* **V$TRANSACTION 뷰** 등에서 트랜잭션을 쉽게 검색할 수 있다. 트랜잭션 이름을 통해 시스템 사전에서 특정 트랜잭션을 찾아 관리할 수 있다.
    
    * 예: 데이터베이스 관리자가 V$TRANSACTION 뷰에서 이름을 검색해 트랜잭션을 추적할 수 있다.
        
* **Redo Log**에 트랜잭션 종료 시 기록되어, 나중에 쉽게 검색할 수 있다. Redo Log는 데이터베이스 복구 시 유용하며, 트랜잭션 이름이 기록되면 이를 통해 빠르게 찾을 수 있게한다.
    
    * 예: 데이터 복구 작업을 할 때, 특정 트랜잭션 이름을 통해 필요한 로그를 쉽게 찾을 수 있게한다.
        

---

### 트랜잭션 코밋(Commit)

**<mark>💡요약: </mark>** 커밋은 트랜잭션의 변경 사항을 영구적으로 반영하며, 데이터를 변경할 때 중요한 과정이다. 커밋이 완료되면, 변경 사항이 디스크에 반영되고 다른 사용자도 변경된 데이터를 볼 수 있게된다.

* **Undo data 생성**: 변경 전 데이터 보존.
    
* **Redo 로그 생성**: 트랜잭션의 변경 사항 기록.
    
* **LOCK 해제**: 트랜잭션 완료 시 잠금 해제.  
    

COMMIT의 과정을 살펴보자

* **DBMS는 SGA에 undo data 정보를 생성: Undo data**는 데이터가 변경되기 전의 값을 저장한다. 이렇게 하면 필요할 때 이전 상태로 되돌릴 수 있게 된다.
    
    * 예: 한 고객의 계좌 잔액을 수정하기 전에, 원래 잔액 정보를 undo data에 저장
        

⬇️

* **undo data는 변경되기 전의 데이터 값을 가짐:** 변경이 되기 전의 데이터 값을 보존하여 문제가 발생했을 때 쉽게 복구할 수 있게 한다.
    

⬇️

* **SGA의 온라인 로그 버퍼에 redo 로그를 생성: Redo 로그**는 트랜잭션의 변경 내용을 기록한다. 이는 데이터베이스가 예기치 않게 종료될 경우 데이터를 복구하는 데 사용된다.
    

⬇️

* **redo 로그는 데이터 블록의 변경 사항과 undo 블록의 변경 사항을 기록:** 트랜잭션에서 변경된 데이터와 그에 대한 복구 정보를 함께 저장한다.
    

⬇️

* **SGA의 데이터베이스 버퍼를 변경:** 실제로 데이터베이스에 반영하기 위해 버퍼의 내용을 업데이트한다.
    

⬇️

* **DBW(database writer)는 데이터베이스 버퍼의 내용을 디스크에 주기적으로 반영:** 변경된 데이터가 일정 주기마다 디스크에 저장된다. 이는 데이터를 영구적으로 보존하기 위함이다.
    

⬇️

* **변경이 이루어진 로우는 LOCK이 걸림**
    
    * 트랜잭션이 끝나면 **LOCK**(잠금)이 해제된다. 이는 다른 사용자가 동일한 데이터를 동시에 수정하지 못하게 하여 데이터 일관성을 유지하는 역할을 한다.
        

---

### 롤백과 트랜잭션 대기 - 세이브포인트(Savepoint)

**<mark>💡요약: </mark>** 세이브포인트는 긴 트랜잭션 중 일부만 되돌리고 싶을 때 유용하게 사용할 수 있다.

* **Savepoint**: 트랜잭션 중 특정 지점 저장.
    
* **Rollback to Savepoint**: 지정한 지점 이후의 변경 사항만 되돌림.
    
* **전체 롤백이 아님**: 트랜잭션의 일부만 취소 가능.  
    

* **세이브포인트는 사용자가 트랜잭션 중간에 특정 지점을 표시: Savepoint**는 트랜잭션 중간에 임시 저장 지점을 설정하는 기능이다. 이를 통해 나중에 해당 지점으로 되돌아갈 수 있게 한다.
    
    * 예: 쇼핑몰에서 여러 제품을 장바구니에 담고, 한 번에 구매를 결정하기 전에 세이브포인트를 설정하여 변경을 쉽게 되돌릴 수 있다.
        
* **Rollback to Savepoint**는 지정한 세이브포인트 이후로 변경이 없도록 복구: 이를 사용하면 설정한 세이브포인트 이후에 이루어진 변경 사항만 되돌린다. 전체 트랜잭션을 취소하는 것이 아닌 부분적인 취소가 가능하다.
    
    * 예: 예를 들어 **SAVEPOINT A**를 설정하고 **B**와 **C** 작업을 했다면, **Rollback to Savepoint A**를 하면 **B**와 **C** 작업만 취소된다.
        
* **트랜잭션 자체의 롤백은 아님:** Savepoint와 Rollback to Savepoint는 전체 트랜잭션을 되돌리는 것이 아니며, 특정 지점 이후의 변경만 되돌린다.
    

**예제**

```sql
ROLLBACK TO SAVEPOINT after_banda_sal;
```

위 명령어는 **after\_banda\_sal**이라는 세이브포인트 이후의 작업만 되돌리게 한다. 이때 **after\_banda\_sal** 이전에 생성한 다른 **SAVEPOINT**는 그대로 유지되지만, 그 이후에 만들어진 **SAVEPOINT**는 사라지게 된다.

---

### 롤백과 트랜잭션 대기 - 실행 예제 #1

**<mark>💡요약: </mark>** 트랜잭션 내에서 데이터를 변경하고, 특정 지점까지 롤백할 수 있는 **SAVEPOINT**를 설정하는 방법이다. 이를 통해 부분적인 변경만 되돌릴 수 있어 데이터 관리에 유연성을 제공한다.

* **COMMIT**: 이전 트랜잭션 종료 및 변경 사항 영구 저장.
    
* **SET TRANSACTION NAME**: 트랜잭션 이름 지정으로 관리 용이.
    
* **UPDATE**: 특정 직원의 급여 수정.
    
* **SAVEPOINT**: 트랜잭션 중간에 임시 저장 지점 설정.  
    

* **t0 - COMMIT**
    
    * **COMMIT** 명령어는 현재 세션에 있는 기존 트랜잭션을 종료하고, 이전에 이루어진 모든 변경 사항을 영구적으로 저장한다.
        
* **t1 - SET TRANSACTION NAME 'sal\_update'**
    
    * 트랜잭션을 시작하고 이름을 **sal\_update**로 지정한다. 트랜잭션 이름을 지정하면 나중에 이 트랜잭션을 쉽게 관리하고 모니터링할 수 있게된다.
        
* **t2 - UPDATE employees SET salary = 7000 WHERE last\_name = 'Banda'**
    
    * 직원 테이블에서 **last\_name**이 **Banda**인 사람의 **salary**를 7000으로 업데이트한다. 이 명령어는 특정 직원의 급여를 수정하는 예다.
        
* **t3 - SAVEPOINT after\_banda\_sal**
    
    * **after\_banda\_sal**이라는 **SAVEPOINT**를 생성한다. 이제 트랜잭션을 되돌릴 때 이 지점까지 되돌릴 수 있게 된다. 예를 들어 이후에 오류가 발생하면 **after\_banda\_sal** 지점으로 복구할 수 있다.
        
* **t4 - UPDATE employees SET salary = 12000 WHERE last\_name = 'Greene'**
    
    * 직원 테이블에서 **last\_name**이 **Greene**인 사람의 **salary**를 12000으로 업데이트한다. 이 명령어는 다른 직원의 급여를 수정하는 예이다.
        

---

### 롤백과 트랜잭션 대기 - 실행 예제 #2

**<mark>💡요약:</mark>** 아래 예제는 여러 SAVEPOINT를 설정하고 롤백을 통해 특정 지점으로 되돌리는 추가적인 방법을 보여준다. 또한 전체 트랜잭션을 롤백하여 모든 변경 사항을 취소하고, 새로운 트랜잭션을 시작하는 과정도 설명한다. 이를 통해 데이터의 일관성을 유지하면서 변경을 관리하는 방법을 이해할 수 있게 된다.

* **SAVEPOINT**: 트랜잭션 중간에 지정 지점 생성 (롤백 기준).
    
* **ROLLBACK TO SAVEPOINT**: 특정 SAVEPOINT 이후 변경 사항 되돌림.
    
* **ROLLBACK**: 트랜잭션의 모든 변경 사항 되돌리고 종료.
    
* **SET TRANSACTION NAME**: 새로운 트랜잭션 시작 및 이름 지정.  
    

* **t5 - SAVEPOINT after\_greene\_sal**
    
    * **after\_greene\_sal**이라는 **SAVEPOINT**를 설정한다. 이는 트랜잭션의 중간 지점으로, 이후 변경 사항을 롤백할 수 있는 기준점이 된다.
        
    * 이 SAVEPOINT를 통해 **Greene**의 급여 변경 작업 이후로 돌아갈 수 있게 된다.
        
* **t6 - ROLLBACK TO SAVEPOINT after\_banda\_sal**
    
    * **after\_banda\_sal**이라는 SAVEPOINT로 롤백한다. 이 명령어는 트랜잭션을 **t3** 단계로 되돌려서 **t4**에서 수행된 **Greene**의 급여 업데이트를 취소하게 된다.
        
    * 트랜잭션은 종료되지 않았으며, 롤백만 실행되었다.
        
* **t7 - UPDATE employees SET salary = 11000 WHERE last\_name = 'Greene'**
    
    * **Greene**의 **salary**를 11000으로 업데이트한다. 이전에 롤백된 **salary** 값을 새롭게 설정하는 단계이다.
        
* **t8 - ROLLBACK**
    
    * 이 명령어는 현재 **sal\_update** 트랜잭션의 모든 변경 사항을 되돌리고 트랜잭션을 종료한다. **Greene**와 **Banda**의 급여 업데이트가 모두 취소된다.
        
* **t9 - SET TRANSACTION NAME 'sal\_update2'**
    
    * 새로운 트랜잭션을 시작하고 **sal\_update2**라는 이름을 지정한다. 이전 트랜잭션이 롤백으로 종료되었기 때문에 새로운 트랜잭션이 시작되게 된다.
        

---

### 롤백과 트랜잭션 대기 - 트랜잭션 대기(Waiting) #1

**<mark>💡요약: </mark>** 새로운 트랜잭션 **sal\_update2**에서 이루어진 데이터 변경을 완료하는 과정을 살펴보자 트랜잭션에서 수행된 모든 변경 사항을 COMMIT으로 영구 저장하여 완료하는 과정이다.

* **UPDATE**: 특정 직원의 급여 업데이트.
    
* **COMMIT**: 트랜잭션 종료 및 모든 변경 사항 영구 저장.  
    

* **t10 - UPDATE employees SET salary = 7050 WHERE last\_name = 'Banda'**
    
    * **Banda**의 **salary**를 7050으로 업데이트한다. 새로운 트랜잭션 **sal\_update2**에서 진행되는 변경 작업 중 하나이다.
        
* **t11 - UPDATE employees SET salary = 10950 WHERE last\_name = 'Greene'**
    
    * **Greene**의 **salary**를 10950으로 업데이트한다. 이 역시 **sal\_update2** 트랜잭션 내에서 수행된 변경 작업이다.
        
* **t12 - COMMIT**
    
    * **sal\_update2** 트랜잭션의 모든 변경 사항을 **COMMIT**한다. 이를 통해 **Banda**와 **Greene**의 급여 업데이트가 영구적으로 저장된다. COMMIT 명령어는 변경 사항을 **online redo log files**에 기록하여 데이터베이스에 확정적으로 반영되도록 보장한다.
        

---

### 롤백과 트랜잭션 대기 - 트랜잭션 대기(Waiting) #2

**<mark>💡요약: </mark>** 트랜잭션 대기 상황은 데이터베이스에서 자원의 충돌을 방지하고 데이터 일관성을 유지하는 중요한 역할을 한다.

* **트랜잭션 대기 (Waiting)**: 하나의 자원을 동시에 접근하려고 할 때, 나중에 실행된 트랜잭션은 잠금이 해제될 때까지 기다림.
    
* **Commit**: 첫 번째 세션에서 Commit을 완료하면 두 번째 세션이 대기 상태에서 벗어나 작업을 수행.
    

---

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730416599969/7ba6f0fa-b1a1-43a6-8b29-a952b2f9e676.png align="center")

* **트랜잭션 대기 (Waiting)** 상황을 보여주는 예제이다. 하나의 트랜잭션이 특정 자원을 사용하고 있을 때, 다른 트랜잭션이 해당 자원을 사용하기 위해 **대기**해야 하는 상황이다. 즉 나중에 실행된 트랜잭션은 해당 자원의 락이 해제 될 때까지 기다려야한다. 이러한 트랜잭션 대기는 데이터 일관성을 유지하고 충돌을 방지하기 위해 필수적이다.
    

---

### 롤백과 트랜잭션 대기 - 트랜잭션 대기(Waiting) #3

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730430401927/c0dcb9c5-5334-4ceb-b4a5-65e9ce60f838.png align="center")

* 첫 번째 세션에서 **Banda**의 급여를 **7000**으로 업데이트하고 **SELECT**문을 통해 결과를 조회하였다. 이 상태에서는 Banda의 급여가 7000으로 설정되었다.
    

---

### 롤백과 트랜잭션 대기 - 트랜잭션 대기(Waiting) #4

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730430443205/0690a3f2-3146-41e3-bfc9-adefe49b149c.png align="center")

* 두 번째 세션에서 **Greene**의 급여를 조회하여 기존 값 **9500**을 확인한다. 이때, 두 번째 세션은 첫 번째 세션에서 이루어진 Banda의 변경 작업을 직접 확인할 수 없다.
    

---

### 롤백과 트랜잭션 대기 - 트랜잭션 대기(Waiting) #5

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730430472558/0a70aca9-8fd7-4262-9384-cd74ccf9fb75.png align="center")

* **첫 번째 세션**: Banda의 Salary를 7000으로 업데이트.
    
* **두 번째 세션**: 첫 번째 세션의 변경 사항이 반영되지 않은 상태로 조회되어 원래 Salary 값(6200)이 표시됨.
    
* **<mark>💡포인트:</mark> Commit되지 않은 변경 사항은 다른 세션에서 볼 수 없음**: 트랜잭션이 Commit되어야 다른 세션에서도 변경된 데이터를 조회할 수 있다.
    

---

### 롤백과 트랜잭션 대기 - 트랜잭션 대기(Waiting) #6

**<mark>💡요약:</mark>** 아래의 예제는 **트랜잭션 대기**가 데이터베이스에서 자원의 충돌을 방지하고 일관성을 유지하기 위해 어떻게 동작하는지 보여주고 있다. **Commit**이 완료되기 전에는 다른 세션이 해당 자원에 접근하지 못하도록 잠금을 걸어 데이터의 무결성을 유지하는 중요한 기능이다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730430504367/96cea8d0-7a74-4227-903f-2cfe2b9c29d4.png align="center")

* **첫 번째 세션**: Banda의 Salary를 7000으로 업데이트했으나 **Commit**하지 않음.
    
* **두 번째 세션**: Banda의 Salary를 10000으로 업데이트 시도했지만, 첫 번째 세션의 **Commit**이 완료될 때까지 대기 상태이기 때문에 아무런 결과가 뜨지 않는다.
    

### 롤백과 트랜잭션 대기 - 트랜잭션 대기(Waiting) #7

**<mark>💡요약:</mark>** 아래 이미지는 **트랜잭션 대기 (Waiting)** 상황에서 **첫 번째 세션에서 Commit**을 실행하면, **두 번째 세션**이 대기하고 있던 작업이 즉시 실행되는 과정을 보여주고 있다.

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1730431452979/b0885109-f332-4f4e-af2d-a5f22b3e7344.png align="center")

* **첫 번째 세션에서 Commit 실행**
    
    * 첫 번째 세션에서 **Banda의 Salary**를 7000으로 업데이트한 후 **Commit**을 실행한다. Commit이 완료되면 해당 트랜잭션의 변경 사항이 데이터베이스에 영구적으로 저장된다.
        
* **두 번째 세션의 대기 상태 해제 및 작업 실행**
    
    * 첫 번째 세션에서 Commit을 완료하자, 두 번째 세션에서 대기하던 **Banda의 Salary를 10000으로 변경**하는 작업이 즉시 실행된다. Commit이 이루어져야만 다른 세션이 해당 데이터에 접근하거나 수정할 수 있게 된다.
        

### 롤백과 트랜잭션 대기 - 트랜잭션 롤백(Rollback)

**<mark>💡요약: </mark>** Rollback은 트랜잭션 도중 문제가 발생했을 때 데이터베이스의 무결성을 유지하고, 원래 상태로 안전하게 복구할 수 있는 기능이다.

* **Rollback**: 트랜잭션을 수행 전 상태로 되돌림.
    
* **undo segment**: 트랜잭션에서 수행한 작업을 반대로 적용.
    
* **락 해제** 및 **세이브포인트 삭제**: 롤백 후 자원 잠금 해제 및 모든 임시 저장 지점 제거.  
    

1. **롤백은 트랜잭션이 수행되기 전 상태로 되돌림**
    
    * Rollback을 실행하면 트랜잭션이 시작되기 전의 상태로 돌아간다. 이는 데이터 무결성을 유지하기 위한 중요한 기능이다.
        
2. **트랜잭션이 롤백되면 더 이상 존재하지 않는 상태가 됨**
    
    * 트랜잭션이 롤백된 후에는 해당 트랜잭션의 변경 사항이 사라지며, 데이터베이스는 마치 해당 트랜잭션이 없었던 것처럼 처리된다.
        
3. **롤백 명령어를 만나면 수행되는 작업**
    
    * **undo segment**를 사용하여 해당 작업을 반대로 적용한다. 예를 들어, 삽입된 데이터는 삭제되고, 업데이트된 데이터는 원래 값으로 복구된다.
        
    * 트랜잭션 중 걸린 **락(lock)**을 해제한다.
        
    * 모든 **세이브포인트 (Savepoint)**를 삭제한다.
        
    * 트랜잭션을 종료한다.
        

```sql
ROLLBACK;
```

위 명령어는 트랜잭션을 모두 되돌려서 원래 상태로 복구시키는 명령어이다. 예를 들어, 트랜잭션 도중에 데이터 수정이 발생했으나 오류가 발견되었을 때 **ROLLBACK**을 통해 변경 사항을 취소할 수 있게 된다.

---
