> For the complete documentation index, see [llms.txt](https://docs.tibero.com/prosync/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tibero.com/prosync/administration/apply/apply-process.md).

# Apply Process

Apply 프로세스에 대하여 설명한다.

## Process 설명

Apply 프로세스는 [architecture](/prosync/introduction/architecture.md)에서도 언급했듯이 ***Chunk*** 단위로 레코드를 전달받고 해당 레코드를 트랜잭션별로 모아준다. 트랜잭션에 Commit이 오면 해당 트랜잭션은 실제 반영 단계에 들어가 대상이 되는 데이터베이스로 반영된다.

본 장에서는, 실제 apply 프로세스의 구조를 상세히 설명한다.

***

## Threads

<figure><img src="https://content.gitbook.com/content/TPAsnFnrfDuUTrH7BU6a/blobs/9WteAv1U9QVKwo68yOCX/4.png" alt=""><figcaption><p>그림 1. Apply Process Architecture</p></figcaption></figure>

Apply 프로세스는 위와 같은 구조를 가지고 있다. 앞서 [Inter Processes/Threads Communication](/prosync/introduction/architecture.md#inter-processes-threads-communication)에서 ProSync의 기본 Thread 구조를 언급한 바 있는데, Apply도 마찬가지로 Main이 되는 Control Thread가 있고 이외에 Worker Thread들이 Control Thread 하위 계층에 구성되어 있다.

동기화에 필요한 Thread는 Construct Thread와 Replay Thread로 크게 두 가지이며, 나머지는 모두 Worker Thread로 구분된다.

{% hint style="info" %}
**참고**

Worker Thread는 종류가 많은 관계로 하단에 간단히 언급한다.
{% endhint %}

### Control Thread

Control Thread는 다른 프로세스와 마찬가지로 모든 통신과 관련된 Multiplexing I/O를 담당한다. 리눅스에선 epoll을 사용하며, 플랫폼별로 k-queue나 pollset 등 각 운영체제에 알맞은 Mux I/O 기능을 사용하도록 설계되어 있다.

### Construct Thread

Construct Thread는 ***Chunk*** 로 들어오는 레코드 데이터들에 대해 트랜잭션으로 재조립한다. Construct라는 말의 의미는 트랜잭션을 다시 조립(**Construct**)하기 때문에 사용된다고 생각하면 된다.

각 레코드에는 본인이 속한 트랜잭션을 구분할 수 있는 일종의 key 값이 존재하는데, 이게 트랜잭션의 ID 일명 (xid)라고 불린다.

Construct는 레코드의 xid 값을 보고 트랜잭션별로 재조립한다.

<figure><img src="https://content.gitbook.com/content/TPAsnFnrfDuUTrH7BU6a/blobs/iENK7pYAgagqTsY9mHvm/5.png" alt=""><figcaption><p>그림 2. Construct의 트랜잭션 Hash</p></figcaption></figure>

{% hint style="info" %}
**참고**

**Construct의 이력 정보 관리**

Construct는 레코드별로 어떤 redo 로그 파일에서 나온 건지에 해당하는 로그 시퀀스 정보와 해당 로그 파일의 몇 번째 레코드에 해당하는지에 대한 정보(wrap#)를 메모리에 계속 저장하게 된다.

redo 로그는 주기적으로 로그 스위치가 일어나고, 이때마다 로그 시퀀스 값이 1개씩 올라가며 새로운 로그파일에 레코드를 작성하게 되는데, 이때마다 메모리에 들고 있던 레코드 정보 및 이력 정보(로그 시퀀스, wrap#)가 물리 디스크 및 데이터베이스에 저장된다.
{% endhint %}

### Replay Thread

Replay Thread는 Commit 레코드가 도달하여 Construct로부터 조립이 완료된 트랜잭션을 전달받는다. 전달받은 트랜잭션은 Commit 레코드의 DB Time(Oracle의 SCN / Tibero의 TSN / ..)에 맞게 직렬화되어 반영되거나, 트랜잭션 내 레코드들의 의존성을 모두 체크하여 병렬로 처리된다.

병렬로 처리하게 될 경우 Replay Thread의 개수가 많아지게 되며, 각 스레드가 DB의 한 세션을 담당하게 된다. 병렬 처리 가능 여부는 Control Thread에서 실시간으로 판단하며, 병렬 처리가 가능할 때 여러 Replay Thread에 일감을 부여하게 된다.

<figure><img src="https://content.gitbook.com/content/TPAsnFnrfDuUTrH7BU6a/blobs/71bm9vq6LMbR51FrDmhD/6.png" alt=""><figcaption><p>그림 3. Replay로 넘어간 트랜잭션</p></figcaption></figure>

### Worker Threads

#### Resource Thread

프로세스의 CPU / Memory 사용량을 실시간으로 수집한다. 수집된 내용은 로그상에 계속해서 남게 되며, ProSync 매니저와 연동 중일 경우, Agent 프로세스를 통해 수집한 값을 ProSync 매니저로 전송한다.

#### Stat Thread

프로세스에서 발생하는 트랜잭션의 시간당 처리량, 일종의 Throughput을 계산한다. ProSync 매니저와 연동 중일 경우, Agent 프로세스를 통해 수집한 값을 ProSync 매니저로 전송한다.

***

## 복구와 Checkpoint

Apply는 재기동이나 재연결 이후에도 중복 반영 없이 이어서 동기화할 수 있도록 복구 상태를 여러 저장소에 나누어 관리한다.

<table><thead><tr><th width="260">저장소</th><th width="200">위치</th><th>역할</th></tr></thead><tbody><tr><td><code>PRS_LCT</code></td><td>Target DB</td><td>반영 스레드가 마지막으로 반영한 TX의 정보. replay/checkpoint의 기준이 된다.</td></tr><tr><td><code>PRS_COMMITTED_TX_LIST</code> (PRS_CTL)</td><td>Target DB</td><td>commit이 완료된 트랜잭션 목록. 재전송된 트랜잭션의 중복 반영 여부 판정에 사용된다.</td></tr><tr><td><code>txh_*</code>, <code>txl_*</code> 파일</td><td><code>$PRS_HOME/var/&#x3C;instance>/tx</code></td><td>아직 commit이 도달하지 않은 미완료 트랜잭션의 export/import에 사용된다.</td></tr></tbody></table>

재연결 시 Apply는 저장된 이력 정보를 Ext에 전달하여(handshake) 재추출 시작점을 결정한다. Ext는 그 지점부터 다시 추출하므로 일부 레코드가 재전송될 수 있으며, Apply는 `PRS_COMMITTED_TX_LIST`를 통해 이미 반영이 완료된 트랜잭션을 건너뛴다.

{% hint style="warning" %}
**주의**

* Target DB를 재설치하거나 `PRS_LCT` 등 메타 테이블이 삭제되면 복구 기준점이 사라져 이어서 반영할 수 없다.
* `$PRS_HOME/var/<instance>/tx` 디렉터리를 삭제하거나 유실하면 미완료 트랜잭션 정보를 복구할 수 없다.
  {% endhint %}

재기동 유형별 복구 절차와 장애 시나리오는 [장애 대응 가이드](/prosync/troubleshooting/apply.md)를 참고한다.
