CodeGym /Các khóa học /SQL SELF /Phân tích các truy vấn và giao dịch hiện tại

Phân tích các truy vấn và giao dịch hiện tại

SQL SELF
Mức độ , Bài học
Có sẵn

Bắt đầu từ căn bản nhé. PostgreSQL cung cấp một bộ công cụ cực xịn để phân tích truy vấn SQL và giao dịch. Ví dụ, các hàm tích hợp như current_query()txid_current() cho phép bạn:

  • Lấy truy vấn SQL hiện đang chạy.
  • Biết truy vấn đó đang chạy trong giao dịch nào.
  • Ghi log các thao tác SQL để phân tích sau này.
  • Theo dõi các vấn đề với giao dịch, nếu code của bạn mong đợi một thứ nhưng lại xảy ra cái khác hoàn toàn.

Tất cả những thứ này sẽ cứu bạn trong các tình huống mà debug thông thường không giúp được gì, hoặc khi bạn muốn phân tích hành vi truy vấn "theo dấu vết".

Tổng quan về các hàm tích hợp

Hàm current_query()

current_query() trả về text của truy vấn SQL hiện tại đang chạy trong kết nối này. "Làm sao nó biết được?" — bạn sẽ hỏi vậy. PostgreSQL theo dõi trạng thái của từng kết nối rất tốt, và hàm này giúp bạn nhìn vào "hậu trường" đó.

Cú pháp:

SELECT current_query();

Ví dụ thực thi:

-- Thực hiện truy vấn trong hàm
DO $$
BEGIN
    RAISE NOTICE 'Truy vấn hiện tại: %', current_query();
END;
$$;

-- Kết quả:
-- NOTICE: Truy vấn hiện tại: DO $$ BEGIN RAISE NOTICE 'Truy vấn hiện tại: %', current_query(); END; $$;

Như bạn thấy ở ví dụ trên, current_query() cho bạn biết text của truy vấn đang chạy. Thông tin này cực kỳ hữu ích khi phân tích các thủ tục phức tạp: bạn biết chính xác cái gì đang được thực thi ngay lúc này!

Hàm txid_current()

Khi nói đến giao dịch, hàm txid_current() là một công cụ cực kỳ tuyệt vời. Nó trả về một định danh duy nhất của giao dịch hiện tại. Điều này đặc biệt hữu ích nếu bạn muốn theo dõi chuỗi thao tác trong cùng một giao dịch.

Cú pháp:

SELECT txid_current();

Ví dụ thực thi:

BEGIN;

-- Lấy ID của giao dịch hiện tại
SELECT txid_current();

-- Kết quả:
-- 564 (ví dụ, định danh)

-- Kết thúc giao dịch
COMMIT;

Các ID giao dịch này có thể dùng để đối chiếu log, phân tích chuỗi hành động và thậm chí debug các hệ thống nhiều người dùng.

Ví dụ sử dụng trong các bài toán thực tế

  1. Ghi log truy vấn hiện tại trong quá trình thực thi.

Đôi khi một thủ tục hoặc hàm chứa rất nhiều truy vấn SQL. Để hiểu chỗ nào bị lỗi, bạn có thể bật log truy vấn SQL hiện tại. Ví dụ:

DO $$
DECLARE
    current_txn_id BIGINT;
BEGIN
    current_txn_id := txid_current();
    RAISE NOTICE 'ID giao dịch hiện tại: %', current_txn_id;

    RAISE NOTICE 'Truy vấn hiện tại: %', current_query();

    -- Ở đây có thể là các thao tác khác của bạn
END;
$$;

Đoạn code này sẽ in ra console định danh giao dịch và text của truy vấn hiện tại. Giờ thì bạn biết chính xác cái gì đang chạy lúc này.

  1. Phân tích giao dịch để tìm ra vấn đề.

Giả sử có tình huống người dùng than phiền bị mất dữ liệu khi cập nhật hàng loạt. Bạn tạo vài thủ tục, mỗi cái chạy trong một giao dịch. Làm sao biết ai là thủ phạm? Đây là ví dụ:

BEGIN;

-- Thêm log giao dịch
DO $$
BEGIN
    RAISE NOTICE 'ID giao dịch hiện tại: %', txid_current();
END;
$$;

-- Thực hiện truy vấn SQL "có vấn đề"
UPDATE orders
SET status = 'processed'
WHERE id IN (SELECT order_id FROM pending_orders);

COMMIT;

Nếu update không thành công, bạn sẽ thấy ngay ID giao dịch liên quan đến thay đổi của bạn. Điều này không chỉ giúp tìm lỗi nhanh mà còn giúp hiểu có xung đột giao dịch hay không.

  1. Ghi log truy vấn để phân tích lịch sử.

Đôi khi bạn không chỉ muốn sửa lỗi hiện tại mà còn muốn nhớ các truy vấn SQL đã chạy. Ví dụ, bạn có thể tạo một bảng để ghi log:

CREATE TABLE query_log (
    log_time TIMESTAMP DEFAULT NOW(),
    query_text TEXT,
    txn_id BIGINT
);

Đây là cách ghi lại truy vấn bằng current_query()txid_current():

DO $$
BEGIN
    INSERT INTO query_log (query_text, txn_id)
    VALUES (current_query(), txid_current());
END;
$$;

Bây giờ trong bảng query_log sẽ lưu thông tin về từng truy vấn đã thực hiện và giao dịch mà nó thuộc về. Đây là công cụ vô giá để phân tích hoạt động của database.

Các case thực tế khi dùng

Ví dụ 1: audit giao dịch

Giả sử bạn đang phân tích thao tác trong một hệ thống nhiều người dùng. Ghi log ID giao dịch (txid_current) giúp bạn nhóm các thao tác theo từng giao dịch.

DO $$
DECLARE
    txn_id BIGINT;
BEGIN
    txn_id := txid_current();
    RAISE NOTICE 'Giao dịch bắt đầu với ID: %', txn_id;

    -- Một thao tác nào đó
    UPDATE users SET last_login = NOW() WHERE id = 123;

    RAISE NOTICE 'Truy vấn hiện tại: %', current_query();
END;
$$;

Ví dụ 2: đơn giản hóa debug thủ tục

Bạn gọi một thủ tục phức tạp và có gì đó không ổn. Bạn có thể nhúng log current_query() ở các bước khác nhau trong hàm để xem truy vấn nào đang chạy:

CREATE OR REPLACE FUNCTION debugged_function() RETURNS VOID AS $$
BEGIN
    RAISE NOTICE 'Truy vấn trước khi update: %', current_query();
    UPDATE data_table SET field = 'debugging';
    RAISE NOTICE 'Truy vấn sau khi update: %', current_query();
END;
$$ LANGUAGE plpgsql;

Khi gọi hàm xong, bạn sẽ nhận được hai thông báo với các truy vấn SQL tương ứng.

Mẹo khi sử dụng

  1. Dùng current_query() để log truy vấn trong các hệ thống nhiều người dùng, giúp bạn hiểu các thao tác nào đang được thực hiện.
  2. txid_current() cực kỳ hợp để phân tích nguồn gốc thay đổi: ở bước nào trong giao dịch của bạn dữ liệu được thêm hoặc sửa.
  3. Đừng quên xóa log không cần thiết khi dùng xong. Thông báo liên tục qua RAISE NOTICE có thể làm chậm hàm của bạn.

Những hàm tích hợp này chính là "kính hiển vi" giúp bạn soi từng chi tiết nhỏ nhất về cách database hoạt động. Chúng sẽ giúp bạn bắt lỗi, tối ưu hiệu năng và hiểu chuyện gì đang xảy ra trong các hệ thống phức tạp. Ở đâu đó, bên trong PostgreSQL, database của bạn đã sẵn sàng chia sẻ bí mật — chỉ còn bạn học cách đọc chúng thôi.

1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Giới thiệu về debug PL/pgSQL
Giới thiệu về debug PL/pgSQL
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION