QueryRunner 테이블 엔진

QueryRunner 테이블 엔진

QueryRunner 테이블에 삽입된 레코드는 엔진이 실행하는 쿼리를 나타내요. 비동기 쿼리 실행, 생성된 쿼리의 일괄 실행, 원격 클러스터로 쿼리 전달, 벤치마크, 퍼징, 셰도우 트래픽(테스트 트래픽) 테스트에 사용할 수 있답니다.

출처: 문서

본문

QueryRunner 테이블에 삽입된 레코드는 엔진이 실행하는 쿼리를 나타냅니다. 이 엔진은 비동기 쿼리 실행, 생성된 쿼리의 일괄 실행, 원격 클러스터로 쿼리 전달, 벤치마크, 퍼징, 셰도우 트래픽을 사용한 테스트에 사용할 수 있어요.

테이블 생성 (Creating a table)

CREATE TABLE runner
(
    query String,
    database String,
    settings Map(LowCardinality(String), String)
)
ENGINE = QueryRunner
SETTINGS
    cluster = 'cluster_name',
    shard = '1',
    mode = 'asynchronous',
    threads = 4,
    max_queue_size = 1000
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }];

테이블은 허용된 컬럼(query, database, settings)의 부분집합으로 생성해야 합니다. query 컬럼은 필수이고, 다른 컬럼은 선택입니다.

Column Type Meaning
query String 실행할 쿼리.
database String 쿼리의 기본 데이터베이스. 비어 있으면 서버의 기본 데이터베이스가 사용됩니다.
settings Map(String, String) 쿼리에 적용되는 설정.

엔진 설정 (Engine settings)

Setting Default Meaning
cluster '' 쿼리를 보낼 클러스터의 이름. 비어 있으면 쿼리가 로컬에서 실행됩니다.
shard '1' 쿼리를 보낼 클러스터 샤드의 1부터 시작하는 인덱스, 또는 쿼리마다 무작위 샤드를 고르는 'random', 또는 각 쿼리를 모든 샤드에서 실행하는 'all'. cluster 설정이 필요합니다.
mode 'asynchronous' 동기 모드에서는 삽입된 배치의 모든 쿼리가 끝난 후 INSERT가 반환됩니다. 비동기 모드에서는 쿼리가 대기열에 들어가는 즉시 INSERT가 반환됩니다.
threads 4 쿼리를 실행하는 배경 스레드 수.
max_queue_size 1000 대기열에 있는 최대 쿼리 수. 대기열이 가득 차면 새로 삽입된 쿼리는 버려지고 오류가 기록됩니다.

세부사항 (Details)

테이블은 INSERT 쿼리만 허용합니다. 쿼리는 "fire and forget" 모드로 실행됩니다. 예외가 발생해도 재시도가 없고, SELECT 쿼리의 결과는 버려집니다(결과를 유지하는 유일한 방법은 INSERT SELECT입니다).

각 쿼리의 성공 여부는 system.query_log 테이블에서 확인할 수 있는데, 이 엔진이 시작한 쿼리는 시작 서버에서 is_internal = 1로 표시됩니다.

대기 중인 쿼리는 메모리에 보관되며 서버 재시작 시에도 유지되지 않습니다. 서버가 종료되면(또는 테이블이 DROP/DETACH되면) 아직 시작되지 않은 쿼리는 버려집니다. 이미 실행 중인 쿼리 중 클러스터로 전달된 것들은 취소되고, 로컬에서 실행 중인 것은 끝날 때까지 대기합니다.

실행할 쿼리 자체가 INSERT라면 그 데이터는 인라인(inline)이어야 합니다 — INSERT ... VALUES (...), INSERT ... SELECT ..., 또는 쿼리 텍스트에 데이터가 있는 INSERT ... FORMAT ... 처럼요. 데이터를 별도의 스트림에서 가져오는 INSERT는 지원되지 않습니다.

로컬 모드와 SQL SECURITY (Local mode and SQL SECURITY)

cluster 설정이 없으면 쿼리는 로컬 서버에서 실행됩니다. 쿼리가 실행되는 사용자는 SQL SECURITY 절에 의해 결정됩니다:

  • INVOKER(기본값): INSERT를 수행한 사용자를 대신하여 쿼리가 실행됩니다.
  • DEFINER: 지정된 DEFINER 사용자를 대신하여 쿼리가 실행됩니다. 삽입된 쿼리가 임의적이므로 그러한 테이블에 INSERT를 부여하면 정의자(definer)의 모든 권한이 위임됩니다.
  • NONE: 쿼리가 사용자 없이 전체 접근 권한으로 실행됩니다. 테이블 생성 시 ALLOW_SQL_SECURITY_NONE 권한(grant)이 필요합니다.

클러스터 모드 (Cluster mode)

cluster 설정이 지정되면 쿼리가 지정된 클러스터로 전송됩니다. 대상 샤드는 shard로 선택됩니다: 고정된 1부터 시작하는 인덱스(기본값 '1'), 각 쿼리에 무작위 샤드를 고르는 'random', 또는 클러스터의 모든 샤드에서 각 쿼리를 실행하는 'all'. 샤드 내의 레플리카는 서버의 load_balancing 설정에 따라 선택됩니다.

database 컬럼은 원격 서버 연결의 기본 데이터베이스를 설정합니다. 기본 데이터베이스는 연결마다 한 번 설정되므로, 각각의 서로 다른 database 값은 고유한 연결 풀을 사용하며, 이 풀은 처음 사용할 때 생성되어 테이블의 수명 동안 재사용됩니다.

DEFINER와 SQL SECURITY는 로컬 모드에서만 효과가 있고, 이를 cluster 설정과 결합하는 것은 오류입니다. 원격 서버에서 쿼리는 클러스터 구성의 자격 증명으로 인증되어 일반 초기 쿼리로 실행됩니다. system.query_log에 is_initial_query = 1과 자체 query_id(이를 만든 INSERT와 연결되지 않음)로 기록됩니다. 시작 서버에서 전달된 쿼리는 system.query_log에 is_internal = 1로 기록됩니다.

엔진이 쿼리 결과를 버리기 때문에 항상 discard_query_data = 1로 전달된 쿼리를 실행합니다. 따라서 SELECT 쿼리의 결과 데이터는 네트워크로 전송되지 않습니다(이것은 settings 컬럼에 설정된 discard_query_data 값을 무시합니다).

쿼리 완료 대기 (Waiting for queries to finish)

비동기 모드에서 다음 쿼리를 사용하여 지금까지 테이블에 제출된 모든 쿼리가 끝날 때까지 차단할 수 있습니다:

SYSTEM WAIT QUERY RUNNER runner;

예시 (Example)

쿼리 로그에서 최근 SELECT 쿼리를 다시 실행(replay)하기:

INSERT INTO runner (query, database, settings)
SELECT query, current_database, Settings
FROM system.query_log
WHERE type = 'QueryFinish' AND is_initial_query AND NOT is_internal AND query_kind = 'Select'
  AND event_time > now() - INTERVAL 1 HOUR;

더 알아보기 (Learn more)