FileLog를 사용하면 다음 작업을 수행할 수 있습니다:
- 로그 파일을 구독합니다.
- 구독한 로그 파일에 새 레코드가 추가될 때 처리합니다.
테이블 생성
path_to_logs– 구독할 로그 파일의 경로입니다. 로그 파일이 있는 디렉터리 경로일 수도 있고, 단일 로그 파일 경로일 수도 있습니다. ClickHouse는user_files디렉터리 내부의 경로만 허용합니다.format_name- 레코드 포맷입니다. FileLog는 파일의 각 줄을 개별 레코드로 처리하므로, 모든 데이터 포맷이 이에 적합한 것은 아닙니다.
poll_timeout_ms- 로그 파일에서 한 번 폴링할 때의 시간 초과 값입니다. 기본값: stream_poll_timeout_ms.poll_max_batch_size— 한 번의 폴링으로 가져올 수 있는 최대 레코드 수입니다. 기본값: max_block_size.max_block_size— 폴링의 최대 배치 크기(레코드 수)입니다. 기본값: max_insert_block_size.max_threads- 파일을 파싱하기 위한 최대 스레드 수입니다. 기본값은 0이며, 이 경우 스레드 수는 max(1, physical_cpu_cores / 4)입니다.poll_directory_watch_events_backoff_init- 디렉터리 감시 스레드의 초기 대기 값입니다. 기본값:500.poll_directory_watch_events_backoff_max- 디렉터리 감시 스레드의 최대 대기 값입니다. 기본값:32000.poll_directory_watch_events_backoff_factor- 백오프 속도입니다. 기본적으로 지수적으로 증가합니다. 기본값:2.handle_error_mode— FileLog 엔진에서 오류를 처리하는 방식입니다. 가능한 값: default(메시지 파싱에 실패하면 예외를 발생시킴), stream(예외 메시지와 원시 메시지를 가상 컬럼_error및_raw_message에 저장함).
설명
전달된 레코드는 자동으로 추적되므로 로그 파일의 각 레코드는 한 번만 계산됩니다. 레코드를 읽는 용도로는SELECT가 그다지 유용하지 않습니다(디버깅 시 제외). 각 레코드는 한 번만 읽을 수 있기 때문입니다. 보다 실용적인 방법은 materialized view(materialized views)를 사용해 실시간 스트림을 만드는 것입니다. 이를 위해 다음을 수행하십시오:
- 이 엔진을 사용해 FileLog 테이블을 만들고, 이를 데이터 스트림으로 간주합니다.
- 원하는 구조의 테이블을 생성합니다.
- 엔진의 데이터를 변환해 앞서 생성한 테이블에 저장하는 materialized view를 생성합니다.
MATERIALIZED VIEW를 엔진에 연결하면 백그라운드에서 데이터 수집이 시작됩니다. 이를 통해 로그 파일의 레코드를 지속적으로 수신하고, SELECT를 사용해 필요한 포맷으로 변환할 수 있습니다.
하나의 FileLog 테이블에는 원하는 만큼 materialized view를 둘 수 있습니다. 이들은 테이블에서 데이터를 직접 읽는 대신 새 레코드(블록 단위)를 받습니다. 따라서 상세 수준이 서로 다른 여러 테이블에 쓸 수 있습니다(그룹화/집계 적용 또는 미적용).
예시:
ALTER를 사용해 대상 테이블을 변경하려면, 대상 테이블과 뷰 데이터 간 불일치를 방지하기 위해 materialized view를 비활성화하는 것이 좋습니다.
가상 컬럼(Virtual columns)
_filename- 로그 파일 이름입니다. 데이터 타입:LowCardinality(String)._offset- 로그 파일 내 오프셋입니다. 데이터 타입:UInt64.
handle_error_mode='stream'일 때 추가되는 가상 컬럼:
_raw_record- 성공적으로 파싱되지 않은 원시 레코드입니다. 데이터 타입:Nullable(String)._error- 파싱 실패 중 발생한 예외 메시지입니다. 데이터 타입:Nullable(String).
_raw_record 및 _error 가상 컬럼은 파싱 중 예외가 발생한 경우에만 채워지며, 메시지가 성공적으로 파싱된 경우에는 항상 NULL입니다.
데이터 내구성
FileLog 엔진은 청크가 포함된 삽입이 커밋되기 전에 해당 청크를 소비한 오프셋을 먼저 기록하므로, 서버가 비정상 종료되면 기록된 오프셋이 실제로 대상 테이블에 반영된 데이터보다 앞서 있을 수 있습니다. 재시작하면 각 로그 파일은 메타데이터 디렉터리에 기록된 오프셋부터 이어서 읽기 때문에 그 사이의 행들은 다시 읽히지 않습니다. 즉, 아무런 오류 없이 유실되고 count() 값만 줄어듭니다. 전원 손실이 아니라 일반적인 프로세스 장애만으로도 이 문제가 발생하는데, 대상 파트가 아직 기록되는 중에 메타데이터 파일이 제자리로 이름이 변경되면서 오프셋이 기록되기 때문입니다.
OS 페이지 캐시가 유실되면 이미 대상 테이블에 기록된 데이터까지 함께 사라질 수 있습니다. 장치 수준의 전원 손실이나 비정상적인 호스트 또는 커널 리셋이 그 예입니다. 오프셋을 담고 있는 메타데이터 파일 자체도 파일이나 해당 디렉터리에 대한 fsync 없이 기록되므로, 그 자체로는 어떠한 내구성도 보장하지 않습니다.
메시지 브로커 엔진과 달리 FileLog에서는 대상을 먼저 내구성 있게 만드는 방식으로 이 문제를 막을 수 없습니다. 오프셋은 읽기 파이프라인 내부에서, 그것이 속한 삽입이 완료되기 전에 기록되므로, 대상 MergeTree 테이블에 fsync_after_insert = 1을 설정하더라도 오프셋이 전진하기 전에 삽입된 파트가 내구성 있게 확정되지는 않습니다. 따라서 FileLog 활용은 로컬 파일에 대한 최선 노력(best-effort) 방식의 테일링으로 간주하십시오. 단 한 행도 유실되어서는 안 되는 환경이라면, 소비된 데이터가 대상에서 검증될 때까지 원본 로그 파일을 보관하여 언제든 다시 활용할 수 있도록 하십시오. 테이블을 삭제하고 다시 생성하면 기록된 오프셋이 폐기되고 파일을 처음부터 다시 읽습니다.