> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ClickHouse 서버보다 먼저 Linux OOM killer의 표적이 되도록 하는 희생용 자식 프로세스로, 서버가 부하를 줄이고 살아남을 기회를 제공합니다.

# OOM 카나리

export const ExperimentalBadge = () => {
  return <div className="experimentalBadge">
            <div className="experimentalIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.25" d="M5.5 2H10.5" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M9.50015 2V6.19625L13.4283 12.7425C13.4738 12.8183 13.4985 12.9049 13.4996 12.9934C13.5008 13.0818 13.4785 13.169 13.435 13.246C13.3914 13.323 13.3283 13.3871 13.2519 13.4317C13.1755 13.4764 13.0886 13.4999 13.0002 13.5H3.00015C2.91164 13.5 2.8247 13.4766 2.74822 13.432C2.67174 13.3874 2.60847 13.3233 2.56487 13.2463C2.52126 13.1693 2.49889 13.082 2.50004 12.9935C2.50119 12.905 2.52582 12.8184 2.5714 12.7425L6.50015 6.19625V2" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.25" d="M4.47656 9.56754C5.30344 9.41254 6.47656 9.47942 7.99969 10.25C10.0153 11.2707 11.4216 11.0569 12.2184 10.7282" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
        </div>
            실험 기능입니다. <u><a href="/docs/docs/beta-and-experimental-features#experimental-features">자세히 알아보세요.</a></u>
        </div>;
};

<ExperimentalBadge />

<Note>
  OOM 카나리는 실험적 기능이며 기본적으로 비활성화되어 있습니다. 프로덕션 환경에서의 검증이 완료될 때까지는 ClickHouse 버전에 따라 동작이
  변경될 수 있습니다.
</Note>

<div id="overview">
  ## 개요
</div>

호스트 또는 메모리 cgroup의 메모리가 고갈되면 Linux OOM(out-of-memory)
killer가 `SIGKILL`로 프로세스를 종료합니다. 보통 가장 많은 메모리를 사용하는 프로세스가 대상이 되는데,
전용 호스트에서는 대개 `clickhouse-server` 자체입니다. 이 경우 서버가 복구할 기회를 얻지 못한 채
전체 서버 프로세스가 중단됩니다.

OOM 카나리는 먼저 종료되는 대상을 바꿉니다. 작은 *희생용*
자식 프로세스를 실행해 해당 프로세스가 OOM 대상이 되기 가장 쉬운 상태를 만들므로,
커널은 서버 대신 이 프로세스를 종료합니다. 그러면 서버는 이 종료를 감지하고,
OOM 이벤트였는지 확인한 뒤 메모리 압박을 완화하여 계속 살아남을 수 있습니다.

카나리는 메모리 한도를 높여 주지 않으며, 올바른 한도 설정을 대체하지도 않습니다
([메모리 오버커밋](/docs/ko/concepts/features/configuration/settings/memory-overcommit) 및
`max_server_memory_usage` 참조). 이는 최후의 방어선으로서, 적은 고정 메모리를
대가로 일시적인 메모리 급증 상황에서 살아남을 가능성을 확보합니다.

<div id="how-it-works">
  ## 작동 방식
</div>

카나리는 별도의 `clickhouse oom-canary` 프로세스입니다. 자체
`oom_score_adj`를 최댓값(`1000`)으로 설정해 커널이 이를 가장 먼저 대상으로 삼게 한 다음,
`oom_canary_size` 바이트(기본값 100 MB)를 할당하고, 메모리 페이지를 실제로 터치한 뒤, `mlock`하여
상주 집합이 실제 메모리를 차지하도록 합니다. 서버가 종료되면 자동으로 함께 종료됩니다.

서버에서는 모니터 스레드가 카나리를(`pidfd`를 통해) 감시하다가,
카나리가 종료되면 다음과 같이 대응합니다:

* cgroup OOM 증거가 **있는 상태에서** `SIGKILL`로 종료됨 → OOM 대응을 실행한 후
  새 카나리를 재시작합니다.
* OOM 증거 **없이** 종료됨(예: 수동 `kill -9`) 또는 일시적 실패로
  종료됨 → 대응은 실행하지 않고 재시작만 합니다.
* 영구적인 설정 실패 또는 서버 종료 → 카나리가 스스로 비활성화됩니다.

OOM 증거는 cgroup v2 `memory.events.local` `oom_kill`
카운터에서만 확인합니다. 이는 의도적으로 해당 cgroup 로컬 값만 사용합니다. 계층형 카운터나 호스트 전체 카운터는
무관한 프로세스로 인해 증가할 수 있으므로, 잘못된 대응이 트리거될 수 있습니다.

OOM이 확인되면 대응은 서로 독립적인 다음 단계를 실행합니다: `FATAL`
메시지를 기록하고, allocator(jemalloc) arenas를 purge하며, 실행 중인 모든
쿼리를 가능한 범위에서 취소하고, 모든 머지와 뮤테이션을 취소하며,
[`system.crash_log`](/docs/ko/reference/system-tables/crash_log)에 이벤트를 큐에 넣습니다.
메모리 압박 상황에서 강제로 I/O를 발생시키면 상황이 더 악화될 수 있으므로 시스템 로그는 동기적으로
플러시하지 않습니다.

<div id="requirements">
  ## 요구 사항
</div>

* **Linux ≥ 5.3.** 모니터는 `pidfd_open`을 통해 카나리를 관리합니다. 이보다 오래된 커널에서는
  카나리가 시작 시 자체적으로 비활성화됩니다. Linux가 아닌 플랫폼에서는 아무 동작도 하지 않습니다.
* **OOM 대응을 위해 `memory.events.local`이 있는 cgroup v2.** 이것이 없으면
  카나리는 `SIGKILL` 이후에도 재시작되지만 OOM을 확인할 수 없으므로
  대응은 실행되지 않습니다(시작 시 경고가 로그에 기록됩니다).
* **`mlock` capability(선택 사항).** 카나리 메모리를 잠그려면
  `CAP_IPC_LOCK` 또는 충분한 `RLIMIT_MEMLOCK`가 필요합니다. 실패하면 카나리가
  경고를 로그에 기록하며 해당 메모리가 스왑될 수 있어 OOM 대상 역할이 약해질 수 있습니다.

<Warning>
  **memory.oom.group**

  서버의 cgroup에서 cgroup v2 `memory.oom.group`이 활성화되어 있으면 커널은
  OOM 시 전체 cgroup을 하나의 단위로 강제 종료합니다. 따라서 서버는
  카나리와 함께 종료되며 대응은 실행되지 않습니다. 이 모드에서는 카나리가 서버를 보호할 수 없으며,
  시작 시 경고가 로그에 기록됩니다.
</Warning>

<div id="configuration">
  ## 구성
</div>

카나리는 [서버 설정](/docs/ko/reference/settings/server-settings/settings)으로 제어되며,
서버 구성의 최상위 요소로 설정하고 재시작 시 적용됩니다.

| Setting                              | Default              | Description                                                                                                                     |
| ------------------------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `oom_canary_enable`                  | `false`              | OOM 카나리를 활성화합니다.                                                                                                                |
| `oom_canary_size`                    | `104857600` (100 MB) | 카나리가 할당하고 실제로 접근하는 바이트 수입니다. 값이 클수록 OOM 대상이 될 가능성이 높아집니다.                                                                       |
| `oom_canary_relaunch`                | `true`               | 카나리가 종료된 후 다시 시작합니다(영구적인 초기 설정 실패 또는 종료인 경우 제외). 단, 아래 제한이 적용됩니다.                                                               |
| `oom_canary_max_rapid_relaunches`    | `10`                 | 과도한 반복을 방지하기 위해 자동 재시작이 비활성화되기 전까지 허용되는 연속 *짧은 간격의* 재시작 최대 횟수입니다. 카나리가 `oom_canary_max_backoff_seconds`보다 오래 실행되면 이 횟수는 재설정됩니다. |
| `oom_canary_initial_backoff_seconds` | `1`                  | 재시작 사이의 초기 지연 시간입니다. 이 값은 최대값에 도달할 때까지 매번 2배로 증가합니다.                                                                            |
| `oom_canary_max_backoff_seconds`     | `60`                 | 재시작 사이의 최대 지연 시간입니다.                                                                                                            |

```xml theme={null}
<clickhouse>
    <oom_canary_enable>1</oom_canary_enable>
    <oom_canary_size>104857600</oom_canary_size>
</clickhouse>
```

<div id="observability">
  ## 관측성
</div>

OOM이 확인되면
[`system.crash_log`](/docs/ko/reference/system-tables/crash_log)에 `signal = 9`이고
`signal_description`에 `OOM Canary`가 언급된 행이 생성됩니다:

```sql theme={null}
SELECT event_time, signal, signal_description
FROM system.crash_log
WHERE signal = 9 AND signal_description LIKE '%OOM Canary%'
ORDER BY event_time DESC;
```

카나리의 수명 주기와 각 OOM 대응 단계도 서버 로그에 기록됩니다.
