카테고리 : MySQL/기술노트

MySQL 로그 체계: 오류·일반·슬로우 로그와 감사 대안

MySQL error log, general query log, slow query log의 역할과 비용을 구분하고 Community 환경의 감사 대안을 운영 관점에서 정리한다.

저자: MySQL 기술 노트 작성: 2026.08.28 약 14분 8,021자
다운로드

MySQL 운영에서 “로그를 확인한다”는 말은 충분히 구체적이지 않다. 서버 시작 실패를 조사할 때와 느린 SQL을 찾을 때, 누가 어떤 객체를 조회했는지 추적할 때 필요한 기록은 서로 다르다. 목적을 구분하지 않고 모든 로그를 켜면 저장 공간과 I/O를 낭비하고, 반대로 비용을 우려해 필요한 로그까지 끄면 장애의 원인과 보안 사건의 흔적을 잃는다.

이 글은 MySQL 8.0 이상을 기준으로 error log, general query log, slow query log의 기록 경로와 운영 비용을 설명한다. 또한 Community MySQL에서 상용 Audit Log 플러그인에 의존하지 않고 감사 요구를 충족할 때 사용할 수 있는 대안을 계층별로 정리한다.

1. 로그는 목적과 생명주기로 분리해야 한다

세 로그는 이름만 다른 동일한 기록물이 아니다.

구분 핵심 질문 대표 내용 평상시 권장 상태
error log 서버 자체에 무슨 일이 생겼는가 시작·종료, 복구, 구성 오류, 플러그인 메시지, 심각한 경고 항상 활성화
general query log 서버가 어떤 접속과 문장을 받았는가 연결·종료, 수신 문장 대개 비활성화, 제한된 진단 창에서만 사용
slow query log 어떤 문장이 기준보다 오래 걸렸는가 실행 시간, 잠금 대기 시간, 검사 행 수, 실행 문장 적절한 임계값으로 상시 활성화 가능
audit 계층 누가 어떤 행위를 했으며 정책상 허용되었는가 사용자·객체·행위·결과, 정책 이벤트 규제·보안 요구에 따라 별도 설계
flowchart LR
    C[클라이언트 연결과 SQL] --> P[MySQL Server]
    P --> E[error log\n서버 생명주기와 오류]
    P --> G[general query log\n수신 연결과 문장]
    P --> S[slow query log\n임계값을 넘은 실행]
    P --> A[감사 계층\n사용자·객체·정책 이벤트]

    E --> O[운영 모니터링]
    G --> D[단기 문제 재현]
    S --> T[성능 튜닝]
    A --> R[보안 조사와 규제 증적]

중요한 차이는 선별 시점이다. general query log는 문장의 성공 여부나 성능과 무관하게 서버가 받은 작업을 넓게 남긴다. slow query log는 실행 후 시간과 검사 행 수 같은 조건으로 문장을 선별한다. error log는 SQL 이력보다 서버 구성 요소의 상태 변화를 기록한다. 감사 로그는 단순 SQL 수집보다 사용자, 객체, 행위, 정책이라는 보안 문맥을 보존해야 한다.

2. error log: 서버 생명주기와 복구의 기준 기록

2.1 무엇을 기록하는가

error log에는 대체로 다음 사건이 기록된다.

  • mysqld 시작과 정상 종료
  • InnoDB crash recovery의 시작, 진행, 완료
  • 구성 변수 오류와 사용 중단 예정 옵션
  • 포트 바인딩, 파일 권한, 데이터 디렉터리 접근 실패
  • 플러그인과 컴포넌트의 초기화 실패
  • replication, Group Replication, TLS와 관련된 서버 수준 오류
  • 비정상 종료 이후 발견된 손상 또는 복구 메시지

따라서 “애플리케이션에서 연결할 수 없다”는 신고가 들어오면 쿼리 로그보다 error log를 먼저 확인해야 한다. 서버가 아직 SQL을 받을 수 없는 상태라면 general log나 slow log에는 원인이 남지 않을 수 있다.

2.2 MySQL 8.0의 구성 요소 관점

MySQL 8.0 error logging은 출력 대상을 단순 파일 하나로만 생각하면 부족하다. log_error_services가 필터와 sink의 파이프라인을 구성하고, log_error_verbosity가 기록할 심각도 범위를 조절한다. 일반적인 파일 sink 외에도 플랫폼과 배포 형태에 따라 systemd journal, Windows Event Log, JSON 형식 sink 등을 사용할 수 있다.

운영자는 다음 세 가지를 함께 확인해야 한다.

  1. 어디로 기록되는가: 파일, 표준 오류, systemd journal, 별도 sink
  2. 어느 심각도까지 남기는가: 오류만 남길지, 경고와 정보도 포함할지
  3. 누가 회전과 보존을 담당하는가: MySQL, 운영체제, 컨테이너 런타임, 로그 수집기

컨테이너에서 log_error 파일만 찾다가 기록이 없다고 판단하는 실수가 흔하다. 이미지의 실행 방식이 표준 오류로 보내는 구조라면 docker logs 또는 중앙 수집 시스템이 실제 원본이다. systemd 기반 호스트에서는 서비스 단위 journal을 먼저 확인할 수 있다.

journalctl -u mysqld --since "30 minutes ago"
docker logs --since 30m <mysql-container>

위 명령은 배포 방식에 따른 예시이며, 서비스명과 컨테이너명은 환경에 맞게 적용해야 한다.

2.3 심각도는 무조건 높게 남기는 것이 정답이 아니다

log_error_verbosity를 높이면 진단 단서는 늘지만, 반복 경고가 중요한 오류를 묻을 수 있다. 반대로 경고를 과도하게 줄이면 인증 실패 추세, 인증서 문제, 사용 중단 예정 설정 같은 사전 징후를 잃는다. 평상시 기준값을 정한 뒤 장애 조사 중에만 변경했다면 종료 시 원복해야 한다.

error log는 비밀 저장소도 아니다. 플러그인이나 외부 도구가 접속 문자열과 토큰을 메시지에 포함하지 않도록 해야 하며, 중앙 로그 전송 구간의 암호화와 열람 권한도 데이터베이스 권한만큼 엄격하게 관리해야 한다.

3. general query log: 넓게 보이지만 비싼 진단 도구

3.1 기록 범위와 해석의 한계

general query log는 클라이언트 연결·종료와 서버가 받은 문장을 폭넓게 보여 준다. 특정 애플리케이션이 실제로 어떤 SQL을 전송하는지, 연결이 반복해서 열리고 닫히는지, ORM이 예상 밖 문장을 생성하는지 확인하는 데 유용하다.

그러나 다음을 혼동하면 안 된다.

  • 기록되었다고 해서 문장이 성공했다는 뜻은 아니다.
  • 실행 시간, 잠금 대기, 검사 행 수를 분석하는 주 도구가 아니다.
  • 바인드 값과 SQL 텍스트에 개인정보나 인증 정보가 포함될 수 있다.
  • 높은 QPS에서 전 문장을 기록하면 동기화·I/O·저장 공간 비용이 빠르게 증가한다.

따라서 general query log는 기본 감사 체계로 상시 켜기보다 대상과 시간을 제한한 진단 창으로 사용하는 것이 안전하다. 켜기 전에 종료 시각, 담당자, 수집 위치, 삭제 시점을 정한다.

3.2 출력 대상과 현재 상태 점검

다음 쿼리는 세 로그의 핵심 전역 변수를 한 번에 점검한다. performance_schema.global_variables를 사용하므로 정렬과 필요한 변수만의 선택이 명확하다.

SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM performance_schema.global_variables
WHERE VARIABLE_NAME IN (
  'log_error',
  'log_error_services',
  'log_error_verbosity',
  'log_output',
  'general_log',
  'general_log_file',
  'slow_query_log',
  'slow_query_log_file',
  'long_query_time',
  'min_examined_row_limit'
)
ORDER BY VARIABLE_NAME;

실행 결과(MySQL 8.0.x):

mysql> SELECT VARIABLE_NAME, VARIABLE_VALUE
    -> FROM performance_schema.global_variables
    -> WHERE VARIABLE_NAME IN (
    ->   'log_error',
    ->   'log_error_services',
    ->   'log_error_verbosity',
    ->   'log_output',
    ->   'general_log',
    ->   'general_log_file',
    ->   'slow_query_log',
    ->   'slow_query_log_file',
    ->   'long_query_time',
    ->   'min_examined_row_limit'
    -> )
    -> ORDER BY VARIABLE_NAME;

+------------------------+----------------------------------------+
| VARIABLE_NAME          | VARIABLE_VALUE                         |
+------------------------+----------------------------------------+
| general_log            | OFF                                    |
| general_log_file       | /var/lib/mysql/07d4f6abd012.log        |
| log_error              | stderr                                 |
| log_error_services     | log_filter_internal; log_sink_internal |
| log_error_verbosity    | 2                                      |
| log_output             | FILE                                   |
| long_query_time        | 10.000000                              |
| min_examined_row_limit | 0                                      |
| slow_query_log         | OFF                                    |
| slow_query_log_file    | /var/lib/mysql/07d4f6abd012-slow.log   |
+------------------------+----------------------------------------+
10 rows in set (0.01 sec)

파일 출력은 FILE, 테이블 출력은 TABLE, 둘 다 사용하면 FILE,TABLE로 지정할 수 있다. TABLE은 SQL로 조회하기 편하지만 일반 테이블과 같은 방식으로 무제한 쌓아 두는 저장소로 간주해서는 안 된다. 파일 출력 역시 회전·압축·보존 정책이 없으면 디스크 고갈로 이어진다.

3.3 제한된 재현 절차

아래 예제는 임시 검증 환경에서 general query log를 mysql.general_log 테이블로 보내고, 표식 문장이 포착되었는지 확인한 뒤 즉시 끈다. 운영 환경에서는 기존 log_output 값을 먼저 기록하고, 진단 종료 후 원래 값으로 복원해야 한다.

SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = ON;
SELECT 'general_log_probe' AS marker;
SET GLOBAL general_log = OFF;
SELECT COUNT(*) AS captured_probe_statements
FROM mysql.general_log
WHERE argument LIKE '%general_log_probe%';

실행 결과(MySQL 8.0.x):

mysql> SET GLOBAL log_output = 'TABLE';

Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL general_log = ON;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT 'general_log_probe' AS marker;

+-------------------+
| marker            |
+-------------------+
| general_log_probe |
+-------------------+
1 row in set (0.00 sec)

mysql> SET GLOBAL general_log = OFF;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT COUNT(*) AS captured_probe_statements
    -> FROM mysql.general_log
    -> WHERE argument LIKE '%general_log_probe%';

+---------------------------+
| captured_probe_statements |
+---------------------------+
|                         1 |
+---------------------------+
1 row in set (0.00 sec)

이 패턴도 높은 트래픽의 운영 서버에 그대로 적용해서는 안 된다. 먼저 재현 가능한 복제본이나 격리된 개발 환경을 선택하고, 운영 서버에서 불가피하다면 수십 초 단위의 짧은 수집 창과 즉시 중단할 담당자를 둔다. 로그 테이블을 조회하는 문장 자체도 기록 대상이 될 수 있으므로 건수는 절대적인 업무 트랜잭션 수가 아니라 “표식 문장이 포착되었다”는 검증 신호로 해석한다.

4. slow query log: 느린 문장을 선별하는 운영 센서

4.1 long_query_time만 보면 부족하다

slow query log의 대표 임계값은 long_query_time이다. 하지만 운영 설계에서는 다음 항목을 함께 본다.

  • slow_query_log: 기능 활성화 여부
  • long_query_time: 기록 대상 실행 시간 임계값
  • min_examined_row_limit: 최소 검사 행 수 조건
  • log_queries_not_using_indexes: 인덱스를 사용하지 않은 문장 추가 기록 여부
  • log_slow_admin_statements: 느린 관리 문장 포함 여부
  • log_slow_replica_statements: replica의 적용 문장 기록 여부와 버전별 지원 상태
  • log_output: 파일과 테이블 중 출력 위치

long_query_time=1이 모든 시스템에 같은 의미를 갖지는 않는다. 온라인 결제 경로에서 300ms는 심각할 수 있고, 야간 집계에서 2초는 정상일 수 있다. 하나의 전역 임계값으로 업무 중요도를 표현할 수 없으므로, slow log는 애플리케이션 지표, Performance Schema, 분산 추적과 결합해야 한다.

4.2 검증 가능한 축소 재현

다음 예제는 현재 검증 세션의 임계값을 0으로 낮추고 짧은 SLEEP() 문장을 실행하여 slow log 포착을 확인한다. 전역 로그 활성화 상태는 실습이 끝나면 즉시 끈다.

SET GLOBAL log_output = 'TABLE';
SET GLOBAL slow_query_log = ON;
SET SESSION long_query_time = 0;
SET SESSION min_examined_row_limit = 0;
SELECT SLEEP(0.02) AS simulated_delay;
SET GLOBAL slow_query_log = OFF;
SELECT COUNT(*) AS captured_slow_statements
FROM mysql.slow_log
WHERE sql_text LIKE '%SLEEP(0.02)%';

실행 결과(MySQL 8.0.x):

mysql> SET GLOBAL log_output = 'TABLE';

Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL slow_query_log = ON;

Query OK, 0 rows affected (0.01 sec)

mysql> SET SESSION long_query_time = 0;

Query OK, 0 rows affected (0.00 sec)

mysql> SET SESSION min_examined_row_limit = 0;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT SLEEP(0.02) AS simulated_delay;

+-----------------+
| simulated_delay |
+-----------------+
|               0 |
+-----------------+
1 row in set (0.02 sec)

mysql> SET GLOBAL slow_query_log = OFF;

Query OK, 0 rows affected (0.00 sec)

mysql> SELECT COUNT(*) AS captured_slow_statements
    -> FROM mysql.slow_log
    -> WHERE sql_text LIKE '%SLEEP(0.02)%';

+--------------------------+
| captured_slow_statements |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set (0.00 sec)

실제 운영에서는 long_query_time=0이 사실상 모든 문장을 기록할 수 있으므로 사용하지 않는 편이 안전하다. 꼭 필요하다면 재현 전용 인스턴스에서만 짧게 사용한다. 운영 서버의 임계값을 바꾸기 전에는 예상 QPS, 문장 평균 길이, 수집 시간으로 대략적인 로그 증가량을 계산하고 디스크 여유와 회전 속도를 확인해야 한다.

4.3 slow log와 Performance Schema의 역할 분담

slow log는 시간 범위가 긴 오프라인 분석과 보존에 강하다. 파일을 수집해 pt-query-digest 같은 도구로 SQL fingerprint별 빈도, 총시간, 평균과 상위 구간을 집계할 수 있다. 반면 Performance Schema의 statement summary는 서버 내부에서 정규화된 digest 단위의 누적 통계를 빠르게 확인하는 데 적합하다.

다음 쿼리는 현재 Performance Schema에 수집된 statement digest 중 총 지연 시간이 큰 항목을 제한적으로 조회한다. 서버 재시작, 테이블 truncate, instrumentation 설정에 따라 결과가 없거나 누적 범위가 달라질 수 있다.

SELECT DIGEST_TEXT,
       COUNT_STAR,
       ROUND(SUM_TIMER_WAIT / 1000000000000, 6) AS total_seconds,
       ROUND(AVG_TIMER_WAIT / 1000000000, 3) AS avg_milliseconds,
       SUM_ROWS_EXAMINED
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT IS NOT NULL
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 5;

실행 결과(MySQL 8.0.x):

아래 표는 검증 실행 결과에서 DIGEST_TEXT, 실행 횟수, 총 지연 시간, 평균 지연 시간의 핵심 열만 발췌한 것이다. 값은 해당 검증 인스턴스의 짧은 누적 구간에 대한 예시이며 운영 기준값이 아니다.

mysql> SELECT DIGEST_TEXT, COUNT_STAR, ... ORDER BY SUM_TIMER_WAIT DESC LIMIT 5;

+---------------------------------------------------------+------------+---------------+------------------+
| DIGEST_TEXT                                             | COUNT_STAR | total_seconds | avg_milliseconds |
+---------------------------------------------------------+------------+---------------+------------------+
| SELECT `SLEEP` (?) AS `simulated_delay`                 |          1 |        0.0202 |           20.217 |
| SELECT `VARIABLE_NAME`, `VARIABLE_VALUE` FROM ...       |          1 |        0.0082 |            8.232 |
| SELECT @@`version_comment` LIMIT ?                      |          3 |        0.0013 |            0.443 |
| SET GLOBAL `slow_query_log` = ON                        |          1 |        0.0012 |            1.237 |
| SET GLOBAL `general_log` = ON                           |          1 |        0.0010 |            0.951 |
+---------------------------------------------------------+------------+---------------+------------------+
5 rows in set (0.00 sec)

두 소스를 경쟁 관계로 볼 필요는 없다. Performance Schema로 현재의 상위 SQL을 신속히 좁히고, slow log로 장애 시간대의 원문과 분포를 보존·분석하는 조합이 일반적이다. 단, digest 통계에도 리터럴이 정규화되기 전 원문이나 스키마 정보가 일부 남을 수 있으므로 접근 권한을 제한한다.

5. “로그가 많다”와 “감사가 된다”는 다르다

감사 요구는 보통 다음 질문에 답해야 한다.

  • 어떤 인증 주체가 접속했는가
  • 어느 시각에 어떤 객체에 어떤 행위를 시도했는가
  • 성공했는가, 실패했는가
  • 권한 변경과 계정 변경은 누가 수행했는가
  • 기록이 사후에 변조되지 않았음을 어떻게 입증하는가
  • 보존 기간과 열람 승인 절차는 무엇인가

general query log는 넓은 SQL 흔적을 제공하지만 감사 정책 엔진은 아니다. 모든 문장을 수집해도 행위 분류, 실패 결과, 객체 기준 필터, 무결성 보장, 보존 승인 절차가 없으면 감사 통제로서 불충분하다. 반대로 요구사항이 “DBA 계정의 DDL과 권한 변경을 1년 보존”처럼 명확하다면 모든 SELECT 원문을 무기한 남기는 것은 과도하다.

6. Community MySQL의 감사 대안

6.1 데이터베이스 내부의 보완 수단

Community 환경에서는 다음 자료를 조합할 수 있다.

  1. error log와 인증 실패 지표: 서버 수준 오류와 접근 이상 징후
  2. binary log: 데이터 변경과 DDL의 복제·복구 기록
  3. Performance Schema: 현재 및 누적 statement, account, connection 관측
  4. slow query log: 성능 문제 문장의 장기 분석
  5. 필요한 시간에만 general query log: 재현과 세밀한 진단
  6. 트리거 기반 업무 감사 테이블: 특정 중요 테이블의 변경 전후 값과 업무 주체

binary log는 시점 복구와 복제에 핵심이지만 완전한 감사 로그는 아니다. 일반 SELECT는 기록되지 않으며, ROW 형식에서는 원래 SQL 문장보다 row event가 중심이다. 보존 기간도 복구 목표에 따라 관리되므로 규제 보존 기간과 일치하지 않을 수 있다.

트리거는 중요한 행 변경을 업무 문맥과 함께 남길 수 있지만 모든 테이블에 무분별하게 적용하면 쓰기 지연, 복제 부하, 스키마 변경 복잡도가 증가한다. 또한 DB 계정과 실제 최종 사용자가 다르면 애플리케이션이 검증된 업무 주체 식별자를 세션 문맥이나 감사 컬럼으로 전달하도록 별도 설계해야 한다.

6.2 데이터베이스 밖의 계층

감사는 단일 MySQL 기능보다 계층형으로 설계하는 편이 견고하다.

  • 프록시 또는 데이터 접근 게이트웨이의 접속·정책 로그
  • 애플리케이션의 인증 주체와 업무 행위 로그
  • 클라우드 제어 평면의 관리자 API 감사 로그
  • 운영체제와 컨테이너 플랫폼의 프로세스·파일 접근 기록
  • 중앙 로그 저장소의 변경 불가 보존, 해시 검증, 역할 기반 접근 제어
  • 보안 정보 및 이벤트 관리 시스템의 상관 분석과 경보

애플리케이션 로그는 “어떤 고객 담당자가 주문 상태를 바꿨는가”라는 업무 문맥을 가장 잘 알지만, DB에 직접 접속한 우회 행위를 놓칠 수 있다. 데이터베이스 로그는 실제 SQL을 보지만 웹 사용자 신원을 모를 수 있다. 두 계층의 상관 키, 시각 동기화, 요청 ID를 설계해야 조사 시 연결할 수 있다.

6.3 상용·관리형 기능을 선택할 때의 기준

Oracle MySQL Enterprise Audit, 배포판별 감사 플러그인, 관리형 데이터베이스의 감사 기능을 검토할 때는 단순 지원 여부보다 다음을 확인한다.

  • 대상 이벤트: 접속, DDL, DML, DCL, SELECT, 실패 행위
  • 사용자·객체·명령별 필터링 정밀도
  • 동기식 기록이 트랜잭션 지연에 미치는 영향
  • 로그 유실 시 fail-open 또는 fail-closed 정책
  • 파일 회전, 암호화, 중앙 전송, 변경 불가 보존
  • 버전 업그레이드와 장애 조치 시 설정 지속성
  • 라이선스와 지원 범위

오픈소스 감사 플러그인을 선택한다면 MySQL minor version과 ABI 호환성, 유지보수 상태, 장애 시 서버 기동에 미치는 영향을 검증해야 한다. “설치된다”는 사실만으로 운영 적합성이 보장되지는 않는다.

7. Aurora MySQL에서 달라지는 운영 경계

Aurora MySQL에서는 DB 인스턴스의 로컬 파일 시스템을 직접 관리하는 방식보다 DB cluster/instance parameter group, Amazon RDS 로그 내보내기, CloudWatch Logs가 운영의 중심이 된다. error, general, slow, audit 계열 로그의 지원 범위와 내보내기 옵션은 Aurora MySQL 엔진 버전에 따라 확인해야 한다.

특히 다음 차이를 고려한다.

  • 파라미터가 동적 적용인지 재부팅이 필요한지 확인한다.
  • writer와 reader 인스턴스의 로그가 분리되므로 장애 조치 전후 인스턴스를 모두 추적한다.
  • CloudWatch Logs 보존 기간은 데이터베이스 로그 활성화와 별도로 설정한다.
  • Performance Insights와 Enhanced Monitoring은 SQL 로그를 대체하지 않지만 성능 상관 분석에 도움이 된다.
  • 관리형 audit 기능을 사용하더라도 필터, 내보내기, 보존, 접근 정책은 별도로 설계한다.
  • 장애 조치 후 새 writer에서도 필요한 로그 설정과 내보내기가 유지되는지 실제 훈련으로 확인한다.

Aurora의 분산 스토리지와 관리형 복구 구조 때문에 호스트 수준의 파일 회전 runbook을 그대로 적용해서는 안 된다. 대신 CloudWatch 수집 지연, 로그 그룹별 보존, KMS 암호화, 구독 필터와 내보내기 비용을 운영 항목으로 관리한다.

8. 장애와 성능 문제를 만드는 흔한 설정

8.1 general log를 무기한 활성화한다

진단이 끝난 뒤 끄지 않아 디스크와 테이블이 계속 증가하는 유형이다. 로그 증가뿐 아니라 민감한 리터럴의 노출 범위도 커진다. 변경 요청에 자동 종료 시각과 원복 명령을 포함해야 한다.

8.2 slow log 임계값을 지나치게 낮춘다

낮은 임계값은 표본을 늘리지만 저장·분석 비용도 키운다. 짧지만 매우 빈번한 SQL은 단건 지연보다 누적 시간을 Performance Schema digest에서 보는 편이 효율적일 수 있다.

8.3 로그 파일과 데이터 파일을 같은 여유 공간으로 계산한다

로그 폭증이 데이터 볼륨을 고갈시키면 진단 기능이 실제 장애 원인이 된다. 별도 파일 시스템 또는 중앙 스트리밍을 검토하고, 파일 크기와 증가율에 임계치 경보를 둔다.

8.4 로그의 시각과 시간대를 맞추지 않는다

DB 서버, 애플리케이션, 프록시, 클라우드 제어 평면의 시간대가 다르면 사건 순서가 뒤집혀 보인다. 저장은 UTC로 통일하고 표시 계층에서 지역 시간대로 변환하는 방식을 우선 검토한다. NTP 동기화 상태도 감사 증적의 일부다.

8.5 로그 접근 권한을 넓게 부여한다

SQL 로그에는 이메일, 토큰, 주민번호와 같은 민감 값이 들어갈 수 있다. 원문 로그 권한은 운영 권한과 분리하고, 중앙 저장소에서는 마스킹·보존·삭제 정책을 적용한다. 장애 대응을 이유로 로그를 개인 장비에 복사하는 절차도 통제해야 한다.

8.6 수집 성공만 확인하고 검색 가능성을 검증하지 않는다

로그 파일이 생성되어도 파서 오류, 전송 지연, 잘못된 인덱스 수명 때문에 중앙 시스템에서 검색되지 않을 수 있다. 정기적으로 알려진 표식 이벤트를 발생시키고 수집부터 검색, 경보까지 종단 검증한다.

9. 목적별 선택 기준

상황 우선 자료 보조 자료 피해야 할 접근
서버 기동 실패 error log, 서비스 관리자 로그 운영체제·컨테이너 이벤트 general log부터 켜려는 시도
특정 요청의 SQL 확인 애플리케이션 trace, 제한적 general log Performance Schema current/history 전 서버 general log 장기 활성화
느린 SQL 상위 분석 slow log, statement digest EXPLAIN ANALYZE, 애플리케이션 지표 단일 실행 시간만 보고 결론
데이터 변경 복구 binary log, 백업 업무 감사 이력 general log를 복구 원장으로 간주
권한 변경 추적 감사 기능, 중앙 보안 로그 error/general log, 변경 승인 기록 slow log로 보안 사건 조사
규제 증적 정책 기반 감사 로그와 변경 불가 저장소 앱·DB·클라우드 로그 상관 분석 로그 한 종류만으로 충족 선언

10. 운영 체크리스트

평상시 기준선

단기 general log 진단 전

  • 원래 general_loglog_output

감사 체계 검토

11. 결론

MySQL의 error log, general query log, slow query log는 각각 서버 상태, 수신 문장, 성능 임계값이라는 다른 관측면을 제공한다. error log는 상시 운영의 기준 기록이고, slow query log는 임계값과 보존 정책을 조정해 지속적으로 활용할 수 있다. general query log는 넓은 가시성만큼 비용과 민감 정보 위험이 크므로 짧고 통제된 진단 수단으로 다루는 편이 안전하다.

감사는 로그를 많이 남기는 문제가 아니라 필요한 행위를 식별하고, 여러 계층의 기록을 상관시키며, 변조 방지와 보존 정책을 입증하는 문제다. 다음 단계에서는 Performance Schema의 statement digest와 wait 계층을 사용해 slow log에서 발견한 SQL을 서버 내부 대기 원인과 연결하는 진단 절차를 다룰 수 있다.