---
title: "Configuration drift 관리: 파라미터 기준선과 변경 이력 추적"
description: "MySQL의 실행값·영속 설정·세션값을 구분하고, 파라미터 기준선 비교와 변경 이력으로 설정 드리프트를 관리한다."
tags: [ MySQL, 운영, DBA, Aurora ]
image: "mysql-report-bg.png"
published: "2026-10-26"
updated: "2026-10-26"
author: "MySQL 기술 노트"
source_url: ""
---

설정 파일이 형상 관리에 들어 있다고 해서 서버가 그 설정대로 동작하는 것은 아니다. 장애 대응 중 실행한 `SET GLOBAL`, 과거에 저장한 `SET PERSIST`, 연결 풀이 유지하는 세션 설정, 관리형 서비스의 재부팅 대기 상태가 각각 다른 값을 만들 수 있다. 업그레이드나 장애 조치 직후에만 성능과 SQL 동작이 달라지는 이유도 이 차이에서 시작하는 경우가 있다.

**Configuration drift는 단순히 두 서버의 값이 다른 상태가 아니라, 승인된 의도와 실제 적용 상태가 어긋난 상태다.** 읽기 전용 replica와 writer의 차이, 메모리 크기에 따른 buffer pool 차이처럼 의도한 차이까지 없애면 오히려 장애를 만든다. 따라서 파라미터 기준선(parameter baseline)은 값 목록뿐 아니라 적용 대상, 예외, 적용 시점, 근거를 함께 정의해야 한다.

이 글은 Community MySQL 8.0/8.4의 설정 계층과 Aurora MySQL의 관리 경계를 설명한다. SQL 실행 결과는 폐기용 MySQL 8.0 인스턴스에서 확인한 것이다. 영속 설정 등록·삭제와 현재 값의 관계는 직접 검증하지만, 서버 재시작 후 재적용이나 실제 Aurora 파라미터 변경을 시험한 결과는 아니다.

## 1. 비교할 값은 하나가 아니라 네 계층이다

### 1.1 승인된 의도와 시작 설정

기준선은 “이 환경의 이 역할에서 이 값을 사용한다”는 승인된 정책이다. 서버 버전 계열, 역할, 인스턴스 크기, 서비스 등급에 따라 구분한다. 모든 서버에 동일한 `max_connections`를 강요하는 방식보다, 연결 예산을 산정한 뒤 역할별 값을 승인하는 편이 안전하다.

시작 설정은 이 의도를 실제로 적용하는 수단이다. Community MySQL에서는 옵션 파일과 시작 인자, 영속 설정 파일 `mysqld-auto.cnf`가 관여한다. `my.cnf`만 비교하면 과거의 영속 설정을 놓칠 수 있다. 반대로 `performance_schema.persisted_variables`가 비어 있다고 해서 “다음 시작 설정이 없다”고 판단해서도 안 된다. 이 테이블은 옵션 파일과 시작 인자 전체를 보여주지 않는다.

### 1.2 현재 전역값과 세션값

`performance_schema.global_variables`는 현재 서버의 전역값을 보여준다. 전역·세션 범위가 모두 있는 변수는 연결이 만들어질 때 전역값을 초기 세션값으로 받는 경우가 많다. 이후 연결 초기화 SQL이나 애플리케이션의 `SET SESSION`이 세션값을 바꿀 수 있다. 변수마다 범위와 변경 효과가 다르므로 일괄적으로 해석하지 않는다.

특히 `sql_mode`, `time_zone`, 연결 문자셋, 격리 수준처럼 SQL 의미에 영향을 주는 항목은 DBA 접속의 전역값만으로 검증할 수 없다. 실제 드라이버와 연결 풀을 거친 세션값을 확인해야 한다. 전역값 변경 뒤 풀 전체를 한꺼번에 재연결하면 접속 폭증이 발생할 수 있으므로 새 연결과 기존 연결의 전환 계획도 필요하다.

```mermaid
flowchart TD
    A[승인된 기준선과 예외] --> B[옵션 파일 또는 파라미터 그룹]
    A --> C[승인된 영속 설정]
    B --> D[시작 및 적용 절차]
    C --> D
    D --> E[현재 전역값]
    E --> F[새 연결의 초기 세션값]
    G[연결 초기화 SQL] --> F
    H[실행 중 설정 변경] --> E
    E --> I[계층별 관측과 비교]
    F --> I
    C --> I
    I --> J[차이 분류와 승인 또는 복구]
    J --> A
```

이 흐름에서 비교기는 값을 수집할 뿐이다. 차이가 발견됐다는 이유만으로 곧바로 `SET GLOBAL`을 실행하는 것은 별도의 위험한 제어 동작이다. 관측과 변경 권한을 분리하는 것이 기본 원칙이다.

## 2. 현재 값과 설정 출처를 함께 관측한다

다음 쿼리는 특정 변수만 허용 목록으로 수집한다. `VARIABLE_SOURCE`는 현재 전역값의 출처를 설명하고, `persisted_value`는 영속 설정에 기록된 값을 보여준다. 두 값은 일치할 수도, 다를 수도 있다.

```sql
SELECT VERSION() AS server_version;
SELECT g.VARIABLE_NAME,
       g.VARIABLE_VALUE AS runtime_value,
       i.VARIABLE_SOURCE,
       p.VARIABLE_VALUE AS persisted_value
FROM performance_schema.global_variables AS g
LEFT JOIN performance_schema.variables_info AS i
  ON i.VARIABLE_NAME = g.VARIABLE_NAME
LEFT JOIN performance_schema.persisted_variables AS p
  ON p.VARIABLE_NAME = g.VARIABLE_NAME
WHERE g.VARIABLE_NAME IN
      ('max_connections', 'group_concat_max_len', 'persisted_globals_load')
ORDER BY g.VARIABLE_NAME;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SELECT VERSION() AS server_version;

+----------------+
| server_version |
+----------------+
| 8.0.46         |
+----------------+
1 row in set (0.00 sec)

mysql> SELECT g.VARIABLE_NAME,
    ->        g.VARIABLE_VALUE AS runtime_value,
    ->        i.VARIABLE_SOURCE,
    ->        p.VARIABLE_VALUE AS persisted_value
    -> FROM performance_schema.global_variables AS g
    -> LEFT JOIN performance_schema.variables_info AS i
    ->   ON i.VARIABLE_NAME = g.VARIABLE_NAME
    -> LEFT JOIN performance_schema.persisted_variables AS p
    ->   ON p.VARIABLE_NAME = g.VARIABLE_NAME
    -> WHERE g.VARIABLE_NAME IN
    ->       ('max_connections', 'group_concat_max_len', 'persisted_globals_load')
    -> ORDER BY g.VARIABLE_NAME;

+------------------------+---------------+-----------------+-----------------+
| VARIABLE_NAME          | runtime_value | VARIABLE_SOURCE | persisted_value |
+------------------------+---------------+-----------------+-----------------+
| group_concat_max_len   | 1024          | COMPILED        | NULL            |
| max_connections        | 30            | COMMAND_LINE    | NULL            |
| persisted_globals_load | ON            | COMPILED        | NULL            |
+------------------------+---------------+-----------------+-----------------+
3 rows in set (0.01 sec)
```

`COMPILED`는 컴파일 기본값, `COMMAND_LINE`은 시작 인자, `DYNAMIC`은 실행 중 변경을 뜻한다. `DYNAMIC`이라는 표시는 “영속화되지 않았다”는 뜻이 아니다. `SET PERSIST`도 현재 값을 변경할 수 있으므로 반드시 영속 테이블과 함께 읽는다. 반대로 `PERSISTED`는 시작 시 영속 설정에서 적용됐다는 출처이며, 이후 실행 중 변경하면 출처가 달라질 수 있다.

`variables_info`의 `SET_TIME`, `SET_USER`, `SET_HOST`, `VARIABLE_PATH`는 마지막 설정 시점·주체·파일 경로를 조사할 때 유용하다. 그러나 이 정보는 **변경 이력 전체가 아니다.** 값을 여러 번 바꿨다면 그 사이의 전환을 복원할 수 없고, 재시작도 정보 해석에 영향을 준다. 시작 시 초기화 시각과 런타임 변경 시각을 구분해야 한다. 수집 결과에는 내부 경로와 접속 주체가 포함될 수 있으므로 외부 보고에는 필요한 항목만 남긴다.

운영 수집기는 서버 식별자, 관측 시각, 엔진 버전, 역할, 수집기 버전도 함께 저장한다. 권한 부족이나 접속 오류로 행을 못 읽었을 때는 이전 정상값을 그대로 최신값처럼 표시하지 말고 `수집 실패`로 표시한다. 변수 없음과 조회 권한 없음도 서로 다른 원인이다.

## 3. 영속 설정 삭제는 현재 값의 복원이 아니다

`SET GLOBAL`은 지원되는 동적 변수의 현재 전역값을 바꾼다. `SET PERSIST`는 현재 값 변경과 영속 저장을 수행한다. `SET PERSIST_ONLY`는 영속 저장만 수행하고 현재 값은 바꾸지 않는다. `RESET PERSIST 변수명`은 영속 항목을 지우지만 현재 전역값을 이전 값으로 되돌리지 않는다.

다음 예제는 **권한을 가진 폐기용 Community MySQL에서만 실행**한다. 기존 영속 항목이 없는 것을 전제로 하므로 운영 서버에 복사해서는 안 된다. `80`과 `60`은 동작 확인용 값이지 권장 연결 수가 아니다. 마지막에 원래 전역값을 복원하고 예제의 영속 항목은 제거한다.

```sql
SET @original_max_connections = @@GLOBAL.max_connections;
SET PERSIST_ONLY max_connections = 80;
SELECT 'persist_only' AS phase,
       @@GLOBAL.max_connections AS runtime_value,
       (SELECT VARIABLE_VALUE
          FROM performance_schema.persisted_variables
         WHERE VARIABLE_NAME = 'max_connections') AS persisted_value;
SET GLOBAL max_connections = 60;
SELECT 'global_changed' AS phase,
       @@GLOBAL.max_connections AS runtime_value,
       (SELECT VARIABLE_VALUE
          FROM performance_schema.persisted_variables
         WHERE VARIABLE_NAME = 'max_connections') AS persisted_value;
RESET PERSIST max_connections;
SELECT 'persist_reset' AS phase,
       @@GLOBAL.max_connections AS runtime_value,
       (SELECT VARIABLE_VALUE
          FROM performance_schema.persisted_variables
         WHERE VARIABLE_NAME = 'max_connections') AS persisted_value;
SET GLOBAL max_connections = @original_max_connections;
SELECT @@GLOBAL.max_connections = @original_max_connections AS runtime_restored;
```

실행 결과(MySQL 8.0.x):

핵심 변경 명령과 조회 결과를 발췌했다. 반복되는 SELECT 원문과 준비·복원 명령 일부는 줄였다.

```text
mysql> SET PERSIST_ONLY max_connections = 80;
Query OK, 0 rows affected (0.00 sec)

+--------------+---------------+-----------------+
| phase        | runtime_value | persisted_value |
+--------------+---------------+-----------------+
| persist_only |            30 | 80              |
+--------------+---------------+-----------------+
1 row in set (0.00 sec)

mysql> SET GLOBAL max_connections = 60;
Query OK, 0 rows affected (0.00 sec)

+----------------+---------------+-----------------+
| phase          | runtime_value | persisted_value |
+----------------+---------------+-----------------+
| global_changed |            60 | 80              |
+----------------+---------------+-----------------+
1 row in set (0.00 sec)

mysql> RESET PERSIST max_connections;
Query OK, 0 rows affected (0.00 sec)

+---------------+---------------+-----------------+
| phase         | runtime_value | persisted_value |
+---------------+---------------+-----------------+
| persist_reset |            60 | NULL            |
+---------------+---------------+-----------------+
1 row in set (0.00 sec)

+------------------+
| runtime_restored |
+------------------+
|                1 |
+------------------+
1 row in set (0.00 sec)
```

이 결과는 세 가지 상태를 구분한다. 영속 등록만 했을 때 현재 값은 유지되고, 실행 중 변경 후에는 현재 값과 저장값이 달라지며, 영속 항목을 삭제해도 현재 값은 그대로 남는다. 따라서 롤백 문서에는 “현재 값 복원”과 “다음 시작에 적용할 설정 복원”을 별도로 적어야 한다.

`persisted_globals_load`가 꺼져 있으면 시작 시 영속 설정을 읽지 않는다는 점도 고려한다. 저장값이 존재한다는 사실만으로 재시작 후 적용을 보장할 수 없다. 재시작 검증에서는 실제 시작 인자, 옵션 파일, 영속 로드 여부, 오류 로그, 재시작 후 SQL 관측을 함께 확인한다. `mysqld-auto.cnf`를 직접 편집하는 대신 서버가 제공하는 영속 설정 명령을 사용하고, 잘못된 정적 설정 때문에 기동하지 못할 때의 별도 복구 절차를 준비한다.

## 4. 전역값이 맞아도 기존 연결은 다를 수 있다

다음 축소 예제는 `group_concat_max_len`을 사용한다. 현재 연결의 세션값을 `1024`로 고정한 뒤 전역값을 `4096`으로 바꾼다. 전역·세션 값이 다른 상태가 실제로 생기는지를 확인하고 둘 다 원래 값으로 복원한다. 이 또한 전역 변경이 포함되므로 폐기용 서버에서만 실행한다.

```sql
SET @saved_global_len = @@GLOBAL.group_concat_max_len;
SET @saved_session_len = @@SESSION.group_concat_max_len;
SET SESSION group_concat_max_len = 1024;
SET GLOBAL group_concat_max_len = 4096;
SELECT @@GLOBAL.group_concat_max_len AS global_value,
       @@SESSION.group_concat_max_len AS current_session_value;
SET GLOBAL group_concat_max_len = @saved_global_len;
SET SESSION group_concat_max_len = @saved_session_len;
SELECT @@GLOBAL.group_concat_max_len = @saved_global_len AS global_restored,
       @@SESSION.group_concat_max_len = @saved_session_len AS session_restored;
```

실행 결과(MySQL 8.0.x):

```text
mysql> SET @saved_global_len = @@GLOBAL.group_concat_max_len;

Query OK, 0 rows affected (0.00 sec)

mysql> SET @saved_session_len = @@SESSION.group_concat_max_len;

Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION group_concat_max_len = 1024;

Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL group_concat_max_len = 4096;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@GLOBAL.group_concat_max_len AS global_value,
    ->        @@SESSION.group_concat_max_len AS current_session_value;

+--------------+-----------------------+
| global_value | current_session_value |
+--------------+-----------------------+
|         4096 |                  1024 |
+--------------+-----------------------+
1 row in set (0.00 sec)

mysql> SET GLOBAL group_concat_max_len = @saved_global_len;

Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION group_concat_max_len = @saved_session_len;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@GLOBAL.group_concat_max_len = @saved_global_len AS global_restored,
    ->        @@SESSION.group_concat_max_len = @saved_session_len AS session_restored;

+-----------------+------------------+
| global_restored | session_restored |
+-----------------+------------------+
|               1 |                1 |
+-----------------+------------------+
1 row in set (0.00 sec)
```

이 시험은 기존 연결의 세션값이 전역 변경에 따라 자동으로 바뀌지 않는 경우를 검증한다. 새 연결의 초기값이나 실제 애플리케이션 풀의 재설정 동작까지 시험한 것은 아니다. 운영 적용에서는 다음 세 관측을 따로 수행한다.

- 이미 업무를 수행 중인 연결의 값과 SQL 결과.
- 변경 이후 새로 만들어진 연결의 값과 연결 초기화 SQL.
- 연결 반환·재사용 또는 드라이버 재접속 뒤의 값과 오류율.

세션 차이는 항상 장애가 아니다. 배치 작업의 승인된 세션 예외라면 대상 작업, 만료 시점, 원복 책임자를 기록하면 된다. 예외를 문서화하지 않은 채 전역 기준선만 강제하는 것이 문제다.

## 5. 기준선 비교기는 누락을 정상으로 처리하면 안 된다

단순 문자열 diff는 오탐과 미탐을 함께 만든다. `ON`과 `1` 같은 표현 차이, 바이트와 용량 단위, 집합 형태의 `sql_mode`, 버전별 변수 제거·이름 변경을 고려해야 한다. 다만 모든 문자열을 무조건 소문자화하거나 정렬해서는 안 된다. 파일 경로처럼 대소문자가 의미를 갖거나 순서가 의미 있는 값은 항목별 정규화 규칙이 필요하다.

다음 SQL은 실제 운영 설정이 아닌 **가정한 정책·관측 데이터**로 판정 로직을 검증한다. `present`, `absent`, `any`는 각각 영속 항목 존재와 값 일치 요구, 영속 항목 부재 요구, 영속 계층 비교 생략을 뜻한다. `absent`가 적절한 이유는 옵션 파일만을 기준선의 적용 수단으로 정한 환경처럼 별도로 설명돼야 한다.

```sql
CREATE TEMPORARY TABLE baseline_demo (
  item VARCHAR(32) PRIMARY KEY,
  expected_runtime VARCHAR(64) NOT NULL,
  persist_rule VARCHAR(8) NOT NULL,
  expected_persisted VARCHAR(64),
  observed_runtime VARCHAR(64),
  observed_persisted VARCHAR(64)
);
INSERT INTO baseline_demo VALUES
('approved_match', '60', 'absent', NULL, '60', NULL),
('runtime_drift', '60', 'any', NULL, '80', NULL),
('persisted_drift', '60', 'present', '60', '60', '80'),
('observation_missing', '60', 'any', NULL, NULL, NULL),
('persisted_missing', '60', 'present', '60', '60', NULL),
('unexpected_persisted', '60', 'absent', NULL, '60', '60');
SELECT item,
       CASE
         WHEN observed_runtime IS NULL THEN 'UNKNOWN'
         WHEN observed_runtime <> expected_runtime THEN 'RUNTIME_DRIFT'
         WHEN persist_rule = 'present'
              AND NOT (observed_persisted <=> expected_persisted)
           THEN 'PERSISTED_DRIFT'
         WHEN persist_rule = 'absent' AND observed_persisted IS NOT NULL
           THEN 'UNEXPECTED_PERSISTED'
         ELSE 'MATCH'
       END AS verdict
FROM baseline_demo
ORDER BY item;
DROP TEMPORARY TABLE baseline_demo;
```

실행 결과(MySQL 8.0.x):

준비 SQL은 축약하고 판정 결과는 전 행을 표시했다.

```text
mysql> CREATE TEMPORARY TABLE baseline_demo (...);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO baseline_demo VALUES (...);
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

+----------------------+----------------------+
| item                 | verdict              |
+----------------------+----------------------+
| approved_match       | MATCH                |
| observation_missing  | UNKNOWN              |
| persisted_drift      | PERSISTED_DRIFT      |
| persisted_missing    | PERSISTED_DRIFT      |
| runtime_drift        | RUNTIME_DRIFT        |
| unexpected_persisted | UNEXPECTED_PERSISTED |
+----------------------+----------------------+
6 rows in set (0.00 sec)

mysql> DROP TEMPORARY TABLE baseline_demo;
Query OK, 0 rows affected (0.00 sec)
```

`<=>`는 NULL 안전 비교다. 일반적인 `<>`로 NULL을 비교하면 조건이 참이 되지 않아 누락된 영속값을 놓칠 수 있다. 관측 자체가 없는 경우를 먼저 `UNKNOWN`으로 분류하는 것도 중요하다. 다만 이 축소 예제는 첫 번째 위반만 반환한다. 실제 비교기는 전역·영속·세션·적용 상태의 위반을 각각 기록하고, 정책 스키마의 유효성도 검사해야 한다. `present`인데 기대값이 없는 잘못된 정책을 승인해서는 안 된다.

기준선의 최소 항목은 변수명, 대상 버전·역할, 기대값 또는 산정식, 값의 단위, 영속화 방식, 재시작 필요 여부, 세션 검증 여부, 예외 만료 시각이다. `MATCH`는 이 비교 규칙 안에서 일치한다는 뜻일 뿐, 성능이나 복구 안전성을 보증하지 않는다.

## 6. 변경 이력은 마지막 설정 정보와 별도로 남긴다

변경 이력에는 “누가 무엇을 실행했는가”뿐 아니라 “왜 이 값이 승인됐고 실제로 어디까지 적용됐는가”가 필요하다. 권장 기록 단위는 한 번의 변경 요청과 그 적용 대상 묶음이다.

1. **요청:** 변경 식별자, 목적, 영향 범위, 담당자, 승인자, 만료 시점.
2. **변경 전:** 기준선 버전, 현재 전역값, 영속값의 존재 여부, 세션 샘플, 적용 대기 상태.
3. **실행:** 실행 주체, 도구 버전, 대상 서버 또는 파라미터 그룹, 변경 수단, 시작·종료 시각.
4. **확인:** 읽기 재조회 결과, 실패 대상, 업무 오류율·지연·자원 사용 변화, 연결 교체 여부.
5. **복구:** 현재 값과 영속값을 각각 복원할 절차, 재시작 또는 연결 갱신 필요성, 복구 완료 증거.

기준선 파일은 Git 등에서 검토하고, 실행 결과는 변경 식별자에 연결된 별도 저장소에 누적한다. 주기적 스냅샷 diff만으로는 두 수집 시점 사이에 변경됐다가 원복된 사건을 알 수 없다. 반대로 SQL 감사 기록만 있으면 최종 적용값을 놓칠 수 있다. **의도 기록, 실행 기록, 결과 관측을 결합**해야 한다.

드리프트 발견 시 우선순위는 데이터 의미·내구성·접근 통제에 영향을 주는 차이를 먼저 조사하는 것이다. 이후 용량과 성능 설정을 다룬다. 차이마다 승인된 예외, 배포 진행 중, 관측 실패, 승인되지 않은 변경으로 분류한다. 장애 대응 중 임시값이 효과를 보였더라도 사후 승인 없이 기준선에 흡수하면 안 된다.

자동 원복은 제한된 변수와 충분한 검증 조건에서만 고려한다. 예를 들어 `max_connections`를 낮추거나 메모리 관련 값을 바꾸는 일은 현재 부하와 연결 수에 영향을 받는다. 문자열 비교가 실패했다는 이유만으로 변경을 반복하면 장애 대응자와 자동화가 서로 값을 덮어쓰는 상황이 생긴다. 변경 잠금, 점검 시간대, 재시도 상한, 중단 조건이 필요하다.

## 7. Aurora에서는 파라미터 그룹과 적용 상태를 함께 본다

Aurora MySQL에서는 Community MySQL의 로컬 설정 파일 관리 절차를 그대로 옮기지 않는다. DB cluster parameter group과 DB parameter group을 구분하고, 파라미터가 어느 계층에 속하는지와 실제 연결된 그룹을 확인한다. 이 글의 `SET PERSIST_ONLY` 실습은 Aurora 운영 절차가 아니다.

AWS의 DB 파라미터 그룹 문서는 동적 파라미터 변경의 즉시 적용과 정적 파라미터 변경의 재부팅 필요성을 구분한다. `pending-reboot`는 선언한 값과 실행 중 값이 아직 다를 수 있다는 신호다. 새 그룹 연결과 기존 그룹의 값 수정도 같은 작업으로 취급하지 말고, 그룹 유형·파라미터의 적용 방식·각 인스턴스 상태를 확인한다. API 성공 응답은 엔진에서 새 값이 적용됐다는 증거를 대신하지 못한다.

Aurora 기준선 수집에는 다음 항목을 추가한다.

- 엔진 버전과 parameter group family, cluster/instance 그룹 이름 및 사용자 변경 항목.
- 파라미터의 데이터 형식, 허용값, 수정 가능 여부, 적용 방식과 적용 상태.
- writer와 각 reader의 실제 전역값, 역할 및 인스턴스 클래스.
- 표현식으로 정의된 값과 엔진에서 평가된 숫자를 구분하는 정규화 규칙.
- 그룹을 공유하는 다른 클러스터·인스턴스의 영향 범위.

AWS CloudTrail의 파라미터 그룹 변경 API 기록은 변경 주체 추적에 유용하지만, DB 연결 안에서 수행한 임의 SQL 변경 이력을 모두 대신하지는 않는다. 관리 API 기록과 SQL 관측 결과를 별도로 연결해야 한다. 장애 조치 뒤에는 승격된 인스턴스와 새 연결을 다시 관측한다. reader에서 허용됐던 예외를 writer에서도 그대로 허용해도 되는지는 역할 정책으로 판단한다.

## 8. 운영 점검표

- [ ] 기준선을 엔진 버전, 역할, 용량 조건별로 구분했는가?
- [ ] 옵션 파일·시작 인자·영속 설정 또는 관리형 파라미터 그룹 중 적용 수단을 명시했는가?
- [ ] 현재 전역값과 영속 저장값을 따로 비교하고, 영속 항목의 존재 정책을 정의했는가?
- [ ] 수집 실패·변수 부재·정책 오류를 정상 일치와 구분하는가?
- [ ] 실제 애플리케이션 연결에서 SQL 의미에 영향을 주는 세션값을 확인했는가?
- [ ] 변경 전 값과 영속 항목 부재까지 기록해 정확한 복구가 가능한가?
- [ ] 마지막 설정 메타데이터와 누적 변경 이력을 구분하는가?
- [ ] 재시작·새 연결·장애 조치 뒤 재검증할 항목이 정해져 있는가?
- [ ] 승인된 예외에 담당자와 만료 시각이 있는가?
- [ ] 자동화가 관측과 변경을 분리하고, 미확인 상태에서 자동 원복하지 않는가?

## 9. 정리

설정 드리프트 관리는 값을 한 번 맞추는 작업이 아니라, 승인된 의도와 적용 경로를 지속적으로 대조하는 운영 체계다. 현재 전역값, 영속 설정, 실제 세션값을 구분하고 누락을 정상으로 처리하지 않아야 한다. 마지막 설정 정보는 조사 단서로 사용하되, 변경 요청과 실행·검증 기록은 별도로 남긴다.

이 기준선은 이후의 업그레이드, 장애 조치, 성능 회귀 분석에서 비교 기준이 된다. 변경 이후 서버가 다시 연결되고 역할이 바뀌더라도 승인된 동작을 유지하는지 확인할 수 있어야 설정 관리가 완료된다.

### 참고 문서

- [MySQL 8.4: 영속 시스템 변수](https://dev.mysql.com/doc/refman/8.4/en/persisted-system-variables.html)
- [MySQL 8.4: variables_info 테이블](https://dev.mysql.com/doc/refman/8.4/en/performance-schema-variables-info-table.html)
- [Aurora: DB 파라미터 그룹 수정](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_WorkingWithParamGroups.Modifying.html)
- [Aurora: DB 클러스터 파라미터 그룹](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_WorkingWithDBClusterParamGroups.html)
