GrepBoardLog

로그 파일을 아무 데나 끌어다 놓으세요

파일 여러 개, 폴더째, .gz 압축도 됩니다. Ctrl+V 로 글을 붙여 넣어도 됩니다.

MySQL 슬로 쿼리 로그 읽는 법

슬로 쿼리 로그는 이미 갖고 있는 가장 값싼 데이터베이스 프로파일러입니다. 항목 하나가 long_query_time 이상 걸린(또는 log_queries_not_using_indexes 가 켜져 있으면 인덱스를 쓰지 않은) 문장 하나이며, 걸린 시간, 잠금을 기다린 시간, 몇 줄을 읽어 몇 줄을 돌려줬는지가 함께 남습니다.

파일을 이 페이지에 놓으면 보드에 바로 나옵니다. 총 시간 순으로 줄 세운 쿼리 지문(파레토 그림), 지문별 읽은 줄 ÷ 보낸 줄, 잠금 대기, 그리고 가장 심하게 훑는 쿼리를 짚는 「먼저 볼 것」 한 줄입니다. 아래 한 줄 명령은 서버에서 같은 질문에 답합니다.

무엇이 남나

다음을 모두 만족하는 문장이 남습니다.

  1. 관리 문장(ALTER TABLE · ANALYZE TABLE · CREATE INDEX · OPTIMIZE TABLE 등)이 아니거나, log_slow_admin_statements 가 켜져 있습니다.
  2. long_query_time 초 이상 걸렸거나, log_queries_not_using_indexes 가 켜져 있고 행을 찾는 데 인덱스를 쓰지 않았습니다.
  3. min_examined_row_limit 줄 이상을 읽었습니다.
  4. log_throttle_queries_not_using_indexes 로 걸러지지 않았습니다.

long_query_time 의 기본값은 10초, 최솟값은 0 이며 마이크로초 단위까지 줄 수 있습니다. 로그는 기본으로 꺼져 있습니다. 최소 설정은 다음과 같습니다.

[mysqld]
slow_query_log      = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time     = 1
log_output          = FILE

파일을 읽을 때 알아 둘 점입니다.

  • 처음 잠금을 얻는 시간은 실행 시간에 들어가지 않습니다.
  • 문장은 실행을 마치고 잠금을 다 푼 뒤에 쓰이므로, 파일 순서가 실행 순서와 다를 수 있습니다.
  • 해석되지 않는 문장(문법 오류)은 남지 않습니다.
  • 문장 안의 비밀번호는 평문으로 남지 않게 고쳐 씁니다.
  • log_timestamps 가 파일 속 시각의 시간대를 정합니다.

항목 하나, 줄마다

# Time: 2026-10-18T10:41:02.551000Z
# User@Host: report[report] @  [10.0.3.5]  Id:  5102
# Query_time: 12.880415  Lock_time: 0.412003 Rows_sent: 1  Rows_examined: 9120400
SET timestamp=1792320062;
SELECT COUNT(*) FROM order_items WHERE created_at >= '2026-10-01';
줄담긴 것
# Time:항목을 쓴 시각입니다.
# User@Host:계정, 클라이언트 호스트나 주소, 연결 번호입니다.
# Query_time:실행 시간(초)입니다.
Lock_time:잠금을 얻는 데 쓴 시간(초)입니다.
Rows_sent:클라이언트로 보낸 줄 수입니다.
Rows_examined:서버 계층에서 읽은 줄 수입니다. 저장 엔진 안의 처리는 세지 않습니다.
SET timestamp=문장 실행을 시작한 Unix 시각입니다.
문장SQL 본문이며 여러 줄일 수 있고 세미콜론으로 끝납니다. 기본 데이터베이스가 바뀌면 use db; 줄이 붙습니다.

위 항목은 한 줄을 돌려주려고 912만 줄을 읽었고, 잠금을 0.4초 기다렸고, 12.9초 걸렸습니다. 이 비율이 가장 먼저 볼 값입니다.

log_slow_extra 를 켜면 늘어나는 칸

log_slow_extra 를 켜면 # Query_time 줄에 문장별 계수가 붙습니다. Thread_id · Errno · Killed · Bytes_received · Bytes_sent, 핸들러 읽기(Read_first · Read_last · Read_key · Read_next · Read_prev · Read_rnd · Read_rnd_next), 정렬 계수(Sort_merge_passes · Sort_range_count · Sort_rows · Sort_scan_count), Created_tmp_disk_tables · Created_tmp_tables · Start · End 입니다. 한 파일에 붙은 줄과 안 붙은 줄이 섞일 수 있으며 칸 수로 구분합니다. 아래 명령은 앞 네 칸만 쓰므로 어느 쪽이든 동작합니다.

읽는 법

신호대개 뜻하는 것다음 할 일
Rows_examined 가 Rows_sent 보다 훨씬 큼몇 줄을 찾으려고 훑고 있습니다. 인덱스가 없거나 쓸 수 없거나, 인덱스 없는 칼럼으로 거릅니다.문장을 EXPLAIN 하고 WHERE · ORDER BY 칼럼을 보십시오.
Query_time 중 Lock_time 이 큰 몫일을 하기보다 다른 트랜잭션을 기다렸습니다.그 시각에 잠금을 쥔 것을 찾으십시오. 긴 트랜잭션, 대량 갱신, DDL.
같은 모양의 문장이 많음한 번은 적당해도 한 쿼리 모양이 전체 시간을 차지합니다.지문으로 묶어 Query_time 을 더하고 1등부터 고치십시오.
항목이 몇 분에 몰림늘 느린 쿼리보다는 부하 급증, 배치 작업, 경합 사건입니다.배포 · cron 작업 · 웹 서버 로그와 시각을 맞춰 보십시오.

문장 모양으로 묶어 Query_time 을 더하는 것이 슬로 로그 요약 도구가 하는 일이며, MySQL 은 이를 위해 mysqldumpslow 를 함께 줍니다. 0.8초짜리라도 하루 5만 번 도는 쿼리가 30초짜리 보고서 한 번보다 중요합니다.

슬로 쿼리 로그용 한 줄 명령

# Query_time 줄은 $3 = Query_time, $5 = Lock_time, $7 = Rows_sent, $9 = Rows_examined 로 나뉩니다. 모두 항목 여러 개가 든 표본 파일로 실행해 확인했습니다.

  • 파일에 문장이 몇 개인가

    grep -c '^# Query_time' slow.log
  • 1초 넘게 걸린 문장은 몇 개인가

    awk '/^# Query_time/ && $3 > 1' slow.log | wc -l
  • 문장 수와 실행 시간 합계

    awk '/^# Query_time/ {s += $3; n++} END {printf "%d statements, %.1f s total\n", n, s}' slow.log
  • 가장 느린 문장과 SQL 첫 줄

    awk '/^# Query_time/ {qt = $3; next} /^(#|SET timestamp|use )/ {next} qt != "" {print qt, $0; qt = ""}' slow.log | sort -rn | head
  • 보낸 한 줄당 읽은 줄 수, 나쁜 순

    awk '/^# Query_time/ && $7 > 0 {printf "%d %s/%s\n", $9/$7, $9, $7}' slow.log | sort -rn | head
  • 잠금 대기가 0.1초를 넘는 문장

    awk '/^# Query_time/ && $5 > 0.1 {print $5, $3}' slow.log | sort -rn
  • 느린 문장을 내는 계정

    awk '/^# User@Host/ {print $3}' slow.log | sort | uniq -c | sort -rn
  • 느린 문장을 내는 클라이언트 주소

    grep '^# User@Host' slow.log | grep -oE '\[[0-9.]+\]' | sort | uniq -c | sort -rn
  • 문장 첫 줄의 모양으로 묶기 — 리터럴을 ? 와 N 으로 바꿈

    awk '/^SET timestamp/ {getline; print}' slow.log | sed -E "s/'[^']*'/?/g; s/[0-9]+/N/g" | sort | uniq -c | sort -rn | head
  • 시간당 항목 수(log_timestamps 가 다르게 정하지 않으면 UTC)

    grep '^# Time:' slow.log | cut -c9-21 | uniq -c

자주 묻는 질문

Query_time 과 Lock_time 은 무엇이 다른가요?

Query_time 은 실행 시간, Lock_time 은 잠금을 얻는 데 쓴 시간입니다. 처음 잠금을 얻는 시간은 실행 시간에 넣지 않습니다.

빠른 쿼리가 슬로 로그에 있는 이유는?

log_queries_not_using_indexes 가 켜져 있고 그 쿼리가 행을 찾는 데 인덱스를 쓰지 않았거나, long_query_time 이 아주 낮게(0 이면 전부 남음) 설정돼 있습니다.

항목 순서가 뒤섞인 이유는?

MySQL 은 문장이 끝나고 잠금을 푼 뒤에 씁니다. 일찍 시작한 긴 문장은 늦게 시작한 짧은 문장보다 뒤에 남습니다. 시작 시각은 SET timestamp 로 보십시오.

Rows_examined 가 Rows_sent 보다 크게 높으면?

몇 줄을 돌려주려고 많은 줄을 읽었다는 뜻입니다. 대개 알맞은 인덱스가 없어 전체나 넓은 범위를 훑습니다. EXPLAIN 으로 확인하십시오.

재시작 없이 슬로 로그를 켤 수 있나요?

됩니다. slow_query_log 와 slow_query_log_file 은 실행 중에 바꿀 수 있는 전역 시스템 변수이며, slow_query_log 를 1 로 두면 켜집니다.

슬로 로그에 비밀번호가 남나요?

문장 속 비밀번호는 그대로 남지 않게 고쳐 씁니다. 다만 SQL 본문과 리터럴 값은 그대로 남으므로 로컬에서 분석하는 것이 중요합니다.

🔒 아무것도 브라우저 밖으로 나가지 않습니다.

로그는 이 브라우저 안, 내 컴퓨터에서만 해석하고 셉니다.