InfraGuard

서비스 ▸ 데이터베이스

등록된 DB에 직접 연결해 SHOW GLOBAL STATUS와 information_schema로 실시간 부하(동시성·처리량)와 스키마 구조를 관제합니다.

개요 — 무엇을 하나

서비스 ▸ 데이터베이스(/service/database)는 등록된 데이터베이스 수집기(access=database)에 직접 연결해 부하 지표를 수집하고 스키마 구조를 분석하는 라이브 관제 화면입니다. 각 DB가 카드 하나로 표현되며, 카드마다 두 축의 부하를 한눈에 보여줍니다.

DB 관제는 2대 부하 축을 중심으로 설계되었습니다.

축 질문 핵심 지표
① 동시 실행 부하 지금 얼마나 몰려 있나 threads_running, 연결 포화율(conn_pct), 대기 쿼리(waiting)
② 처리량·비효율 얼마나 처리하고, 얼마나 낭비하나 QPS(Δquestions/Δt), slow rate(Δslow_queries/Δt)

여기에 더해 스키마 분석(총 용량·상위 DB·용량 상위 테이블·엔진 구성), 효율 점수(캐시 적중률·인덱스 사용률), InnoDB 메모리 관리(dirty page flush·checkpoint) 블록을 제공합니다.

이 화면은 대상 DB에 에이전트를 설치하지 않습니다. InfraGuard 앱이 등록된 접속정보로 원격 MySQL/MariaDB에 직접 붙어 SHOW GLOBAL STATUS·information_schema를 조회할 뿐입니다.

언제 쓰나

화면 구성

상단 KPI

KPI 의미
DB 수 등록된 access=database 수집기 총 개수
정상 / 주의 / 중단 카드 상태(up/degraded/down) 집계
총 QPS 전 카드 QPS 합계
연결 수 전 카드 threads_connected 합계

카드 헤더

① 동시 실행 부하

② 처리량·비효율

카드 풋 — 효율 · lock

지표 계산 등급
캐시 적중률 1 − Δinnodb_buffer_pool_reads / Δinnodb_buffer_pool_read_requests 우수 ≥99.5% · 양호 ≥98% · 보통 ≥90%
인덱스 사용률 Δhandler_read_key / (Δhandler_read_key + Δhandler_read_rnd_next) 우수 ≥90% · 양호 ≥70% · 보통 ≥40%
lock innodb_row_lock_time_avg(평균 row-lock 대기 ms) 낮을수록 좋음

각 지표의 텍스트(캐시·인덱스·lock·checkpoint)에는 교육용 popover가 붙어 원인과 개선법(예: innodb_buffer_pool_size 증설, 커버링 인덱스, 갭 락 회피)을 설명합니다.

스키마 분석 (접이식)

기본은 접힌 상태이며 [펼치기]로 확장합니다. information_schema.tables에서 집계한 총 용량·테이블 수·스키마 수·용량 상위 스키마 8개·용량 상위 테이블 14개·엔진 구성을 보여줍니다.

스키마 분석은 서버에서 본질적으로 느린 쿼리(실측 약 3.5초)라 30분 장기 캐시로 우회합니다. 스케줄러(infr:collect-db)가 캐시를 워밍하므로 웹 요청은 항상 캐시 히트합니다. 캐시가 비어 있으면 이 섹션은 잠시 숨겨졌다가 다음 폴링에서 나타납니다.

InnoDB 메모리 관리 (dirty page flush)

카드 배치

카드 그리드는 드래그로 순서 변경(SortableJS · 순서 localStorage 영속) + row-span masonry로 배치됩니다. 화면은 30초 폴링으로 갱신됩니다.

사용법

  1. 먼저 Administration ▸ 수집기에서 접근 방식 database 수집기를 등록합니다. host/port/database/username + 비밀번호(수집기에 Crypt 암호화 저장)를 입력하거나, cred_ref = env:PREFIX로 .env의 기존 자격 세트를 재사용합니다.
  2. /service/database에 진입하면 등록된 DB가 카드로 나열됩니다. 진입 시 최신 샘플이 60초보다 오래됐으면 즉석 1회 샘플(ensureFresh)을 뜹니다.
  3. 카드 헤더의 상태 배지로 문제 DB를 먼저 식별하고, 두 부하 축(동시성/처리량)에서 원인을 좁힙니다.
  4. 스키마 분석 [펼치기]로 용량 상위 스키마·테이블을 확인합니다(masonry가 높이 변화를 자동 재배치).
  5. 카드를 드래그해 관심 DB를 위로 배치합니다(순서는 브라우저에 저장).

cred_ref로 자격 재사용

cred_ref = env:PREFIX이면 .env에서 다음 키를 읽어 비밀을 DB에 저장하지 않습니다.

예: env:STATS_DB → blue 서버, env:STATS_GLORY_DB → glory 서버.

서버 전역 대기 쿼리를 보려면

waiting 집계를 서버 전역으로 하려면 모니터 계정에 PROCESS 권한이 필요합니다. 없으면 자기 연결만 집계됩니다. 최소권한 모니터 계정 예:

CREATE USER 'infra_monitor'@'%' IDENTIFIED BY 'YOUR_DB_PASSWORD';
GRANT PROCESS, SELECT ON *.* TO 'infra_monitor'@'%';
FLUSH PRIVILEGES;

scope 판정(PROCESS 유무)은 계정 고정이라 1시간 캐시됩니다. 나중에 권한을 부여하면 최대 1시간 뒤 반영됩니다(즉시 반영은 캐시 클리어).

데이터 소스

원천 쿼리 (원격 DB에서 실행)

쿼리 용도
SHOW GLOBAL STATUS threads·questions·slow_queries·bytes·buffer pool·handler·InnoDB 카운터 전량
SELECT @@GLOBAL.max_connections 등 max_connections, InnoDB flush 설정(1h 캐시)
information_schema.processlist 대기 쿼리 수 + scope 판정
information_schema.tables 스키마 분석(30분 캐시)
SHOW ENGINE INNODB STATUS checkpoint age(LSN − last checkpoint · PROCESS 필요)
SHOW GRANTS FOR CURRENT_USER() PROCESS 권한 판정(scope)

저장 테이블

수집한 샘플은 infr_db_metric(마이그레이션 000681) 시계열에 적재됩니다. 누적 카운터(questions/slow_queries/bytes_*)도 함께 저장해 다음 샘플에서 delta로 QPS·slow rate·효율 점수를 계산합니다.

infr_db_metric
  collector_id  host  sampled_at  uptime_sec
  threads_connected/running/cached  max_connections  conn_pct
  waiting  waiting_scope
  questions  slow_queries  qps  slow_qps
  bytes_received/sent  recv_bps/sent_bps  innodb_row_lock_waits
  ok  message  raw(json: 효율·InnoDB 메모리 관리 파생값)

연결 누수 금지(§[1040] 교훈). 매 샘플마다 런타임 커넥션을 만들고 finally에서 즉시 DB::purge 합니다. PDO 타임아웃(기본 5초)으로 웹 요청·스케줄이 원격 지연에 묶이지 않게 합니다. 이 규율이 깨지면 공유 MySQL의 max_connections가 고갈되어 프로덕션까지 영향을 줍니다.

수집 스케줄 · 게이팅

시계열은 아티즌 커맨드 infr:collect-db가 채웁니다. 단발 실행 후 종료(데몬 아님)하며 스케줄러가 매분 호출합니다.

# 특정 수집기만 즉시 1회(게이트 우회)
php artisan infr:collect-db --key=db@blue --force

운영 정책(Administration ▸ 운영 정책 · OpsPolicy)이 스케줄 실행을 게이팅합니다.

설정 기본 의미
db_collect_mode economy economy=콘솔 사용자(프레즌스)가 있을 때만 수집 · always=상시
db_collect_interval_sec 60 수집 주기(초). 매분 tick이지만 실효 주기는 이 값

degraded/down 판정 임계값

DbCollectorService::statusOf가 OpsPolicy::dbThresholds()로 판정합니다.

사유(reason) 조건 기본 임계
conn_saturation(연결 포화) conn_pct ≥ 80%
high_concurrency(높은 동시성) threads_running ≥ 40
query_backlog(쿼리 밀림) waiting ≥ 5
slow_query_rate(slow 증가) slow_qps ≥ 1/s
down(중단) 샘플 없음·ok=false, 또는 최신 샘플이 5분보다 오래됨(stale) —

사유가 하나라도 있으면 주의(degraded), 없으면 **정상(up)**입니다.

권한

문제해결 · FAQ

카드가 "중단(down)"으로 뜹니다

QPS·slow rate·효율 점수가 "—"로 보입니다

파생값은 이전 성공 샘플과의 delta로 계산합니다. 첫 샘플이거나, DB 재시작으로 uptime이 줄었거나(카운터 리셋), 카운터가 역행하면 신뢰할 수 없어 null(—)로 둡니다. 두 번째 샘플 이후 정상 표시됩니다.

대기 쿼리가 "자기 연결만"이라고 나옵니다

모니터 계정에 글로벌 PROCESS 권한이 없어 information_schema.processlist에서 자기 연결만 보입니다. 위 서버 전역 대기 쿼리를 보려면 SQL로 PROCESS를 부여하세요(반영은 scope 캐시 만료 최대 1시간 뒤).

메모리 관리·checkpoint 섹션이 비어 있습니다

스키마 분석이 잠깐 비었다가 나타납니다

analysisCached는 캐시 조회 전용입니다. 최초 진입 시 캐시가 비어 있으면 섹션이 숨겨지고, 스케줄러가 캐시를 워밍한 뒤 다음 30초 폴링에서 나타납니다. 실패는 30초만 캐시(성공은 30분)하므로 일시 장애가 오래 고정되지 않습니다.

관련 항목

데이터베이스 관제 — 연결 포화·QPS·슬로우 쿼리
데이터베이스 관제 — 연결 포화·QPS·슬로우 쿼리