일단 기본부터 시작하자. PostgreSQL은 SQL 쿼리랑 트랜잭션을 분석할 수 있는 멋진 도구들을 제공해. 예를 들어, 내장 함수 current_query()랑 txid_current()를 쓰면 이런 걸 할 수 있어:
- 현재 실행 중인 SQL 쿼리를 가져오기.
- 어떤 트랜잭션 안에서 쿼리가 실행되고 있는지 알기.
- SQL 작업을 로그로 남겨서 나중에 분석하기.
- 트랜잭션 문제 추적하기 — 코드가 뭔가를 기대하는데 실제로는 완전 다른 일이 벌어질 때!
이런 기능들은 기본 디버깅 출력만으로는 부족할 때나, 쿼리 동작을 "흔적 따라" 분석하고 싶을 때 진짜 유용해.
내장 함수 살펴보기
current_query() 함수
current_query()는 현재 연결에서 실행 중인 SQL 쿼리의 텍스트를 반환해. "어떻게 알지?"라고 궁금할 수 있는데, PostgreSQL은 각 연결의 상태를 잘 추적하고 있어서 이 함수로 그 "백스테이지"를 들여다볼 수 있어.
문법:
SELECT current_query();
실행 예시:
-- 함수 안에서 쿼리 실행
DO $$
BEGIN
RAISE NOTICE '현재 쿼리: %', current_query();
END;
$$;
-- 결과:
-- NOTICE: 현재 쿼리: DO $$ BEGIN RAISE NOTICE '현재 쿼리: %', current_query(); END; $$;
예시에서 보듯이, current_query()는 실행 중인 쿼리 텍스트를 알려줘. 복잡한 프로시저를 분석할 때 진짜 유용해 — 지금 뭐가 실행되고 있는지 바로 알 수 있으니까!
txid_current() 함수
트랜잭션을 다룰 때 txid_current()는 정말 쓸만한 도구야. 이 함수는 현재 트랜잭션의 고유 ID를 반환해. 한 트랜잭션 안에서 작업 순서를 추적하고 싶을 때 특히 좋아.
문법:
SELECT txid_current();
실행 예시:
BEGIN;
-- 현재 트랜잭션 ID 가져오기
SELECT txid_current();
-- 출력:
-- 564 (예시로, 이게 트랜잭션 ID야)
-- 트랜잭션 종료
COMMIT;
이 트랜잭션 ID들은 로그 매칭, 작업 순서 분석, 멀티유저 시스템 디버깅에도 쓸 수 있어.
실전에서 쓰는 예시들
- 실행 중인 쿼리 로그 남기기.
프로시저나 함수에 SQL 쿼리가 여러 개 들어있을 때, 어디서 문제가 생겼는지 알고 싶으면 현재 SQL 쿼리를 로그로 남기면 돼. 예를 들어:
DO $$
DECLARE
current_txn_id BIGINT;
BEGIN
current_txn_id := txid_current();
RAISE NOTICE '현재 트랜잭션 ID: %', current_txn_id;
RAISE NOTICE '현재 쿼리: %', current_query();
-- 여기에 추가 작업이 들어갈 수도 있어
END;
$$;
이 코드는 콘솔에 트랜잭션 ID랑 현재 쿼리 텍스트를 출력해. 이제 뭐가 실행되고 있는지 딱 알 수 있지.
- 트랜잭션 분석해서 문제 찾기.
예를 들어, 유저들이 대량 업데이트할 때 데이터가 사라진다고 불평한다고 해보자. 여러 프로시저가 각각 하나의 트랜잭션 안에서 실행돼. 누가 문제인지 어떻게 알지? 예시를 보자:
BEGIN;
-- 트랜잭션 로그 남기기
DO $$
BEGIN
RAISE NOTICE '현재 트랜잭션 ID: %', txid_current();
END;
$$;
-- "문제" SQL 쿼리 실행
UPDATE orders
SET status = 'processed'
WHERE id IN (SELECT order_id FROM pending_orders);
COMMIT;
업데이트가 안 되면, 바로 어떤 트랜잭션에 변경이 묶여있는지 ID로 확인할 수 있어. 에러 찾기도 쉽고, 트랜잭션 충돌이 있었는지도 파악할 수 있지.
- 쿼리 로그 남겨서 히스토리 분석하기.
가끔은 지금 문제만 고치는 게 아니라, 어떤 SQL 쿼리들이 실행됐는지 기록을 남겨야 할 때도 있어. 예를 들어, 로그용 테이블을 만들 수 있어:
CREATE TABLE query_log (
log_time TIMESTAMP DEFAULT NOW(),
query_text TEXT,
txn_id BIGINT
);
이렇게 current_query()랑 txid_current()를 써서 쿼리를 기록할 수 있어:
DO $$
BEGIN
INSERT INTO query_log (query_text, txn_id)
VALUES (current_query(), txid_current());
END;
$$;
이제 query_log 테이블에 실행된 쿼리랑 트랜잭션 정보가 다 남아. 데이터베이스 분석할 때 진짜 꿀템이지.
실전 케이스
예시 1: 트랜잭션 감사
멀티유저 시스템에서 작업을 분석한다고 해보자. 트랜잭션 ID(txid_current)를 로그로 남기면 한 트랜잭션 안의 작업들을 묶어서 볼 수 있어.
DO $$
DECLARE
txn_id BIGINT;
BEGIN
txn_id := txid_current();
RAISE NOTICE '트랜잭션 시작 ID: %', txn_id;
-- 어떤 작업
UPDATE users SET last_login = NOW() WHERE id = 123;
RAISE NOTICE '현재 쿼리: %', current_query();
END;
$$;
예시 2: 프로시저 디버깅 쉽게 하기
복잡한 프로시저를 실행했는데 뭔가 꼬였어. 함수의 여러 단계에 current_query() 로그를 넣으면 어떤 쿼리가 실행됐는지 바로 볼 수 있어:
CREATE OR REPLACE FUNCTION debugged_function() RETURNS VOID AS $$
BEGIN
RAISE NOTICE '업데이트 전 현재 쿼리: %', current_query();
UPDATE data_table SET field = 'debugging';
RAISE NOTICE '업데이트 후 현재 쿼리: %', current_query();
END;
$$ LANGUAGE plpgsql;
함수 호출이 끝나면, 각각의 SQL 쿼리 로그가 두 번 출력될 거야.
활용 꿀팁
- 멀티유저 시스템에서
current_query()로 쿼리 로그를 남기면 어떤 작업이 실행되는지 파악하기 좋아. txid_current()는 변경의 출처를 분석할 때 최고야 — 트랜잭션의 어느 단계에서 데이터가 추가/수정됐는지 알 수 있어.- 로그 남기는 게 끝나면 꼭 불필요한 로그는 지워줘.
RAISE NOTICE로 계속 알림을 띄우면 함수 실행이 느려질 수 있어.
이런 내장 함수들은 데이터베이스를 "현미경"처럼 들여다볼 수 있게 해줘. 에러 잡고, 성능 개선하고, 복잡한 시스템에서 무슨 일이 벌어지는지 이해하는 데 진짜 도움돼. PostgreSQL 안 어딘가에서, 네 데이터베이스는 이미 비밀을 공유할 준비가 돼 있어 — 이제 그걸 읽는 법만 배우면 돼!
GO TO FULL VERSION