CodeGym /Các khóa học /SQL SELF /Cài đặt alert và thông báo khi có sự cố

Cài đặt alert và thông báo khi có sự cố

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

Tụi mình ai cũng muốn biết về sự cố trước khi server sập hoặc làm khổ user. PostgreSQL có sẵn mấy tool để tạo thông báo và chạy task: pg_notify và pg_cron. Nói đơn giản, đây là đồng hồ báo thức và lịch trình riêng cho database của tụi mình luôn.

Ví dụ nhé: bạn có database cho khóa học đổi tiền tệ, tự dưng một process nào đó khóa hết mấy process còn lại. Thay vì phải kiểm tra thủ công database liên tục, bạn có thể cài alert để biết ngay khi có chuyện. Còn để kiểm tra định kỳ tình trạng database thì pg_cron là chân ái. Giờ mình cùng tìm hiểu chi tiết nhé.

Thông báo nhanh từ database: pg_notify

Bắt đầu với pg_notify nhé. Đây là function built-in của PostgreSQL, cho phép gửi thông báo từ database lên một "kênh" nhất định. Bạn có thể dùng nó để báo hiệu các sự kiện như query chạy lâu, phát hiện deadlock hoặc mấy tình huống bất thường khác.

Cú pháp pg_notify khá đơn giản:

NOTIFY <channel>, <message>;
  • channel — tên kênh sẽ nhận thông báo.
  • message — chuỗi text của thông báo.

Lấy ví dụ dùng pg_notify nhé. Giả sử mình muốn tạo thông báo khi phát hiện có deadlock:

DO $$
BEGIN
    IF EXISTS (
        SELECT 1
        FROM pg_locks l
        JOIN pg_stat_activity a
        ON l.pid = a.pid
        WHERE NOT l.granted
    ) THEN
        PERFORM pg_notify('alerts', 'Deadlock trong database!');
    END IF;
END $$;

Đoạn code này kiểm tra xem có deadlock chưa xử lý không, nếu có thì gửi thông báo lên kênh alerts.

Để lắng nghe thông báo, dùng lệnh LISTEN ở một kết nối khác:

LISTEN alerts;

Bây giờ, nếu pg_notify gửi message lên kênh alerts, bạn sẽ thấy thông báo ngay trên console.

Ví dụ:

NOTIFY alerts, 'Ê, có deadlock kìa!';

Ở kết nối khác, nơi bạn đã chạy LISTEN alerts, bạn sẽ nhận được ngay:
NOTIFY: Ê, có deadlock kìa!

Ứng dụng của pg_notify không chỉ dừng ở thông báo đơn giản đâu. Bạn có thể kết hợp với trigger để tự động báo khi có dữ liệu mới, sửa đổi hoặc xóa:

Thông báo khi có record mới

CREATE OR REPLACE FUNCTION notify_new_record()
RETURNS trigger AS $$
BEGIN
    PERFORM pg_notify('table_changes', 'Có record mới được thêm vào table!');
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER record_added
AFTER INSERT ON your_table
FOR EACH ROW EXECUTE FUNCTION notify_new_record();

Bây giờ, mỗi khi có record mới vào table your_table, bạn sẽ nhận được thông báo liền.

Bạn sẽ học kỹ hơn về trigger và function built-in ở mấy bài sau nha :P

Lỗi thường gặp và cách tránh

Nếu bạn dùng LISTEN mà không thấy thông báo, hãy kiểm tra:

  1. Bạn có đang ở cùng kết nối nơi gửi thông báo không.
  2. Kiểm tra tên kênh đã đúng chưa.
  3. Đảm bảo bạn gọi pg_notify trong transaction đã được commit (COMMIT).

Lên lịch task trong PostgreSQL: pg_cron

pg_cron là extension cho PostgreSQL, cho phép chạy task theo lịch, giống như cron trên Linux vậy. Ví dụ, bạn có thể cài task kiểm tra deadlock định kỳ hoặc thu thập thống kê.

Tạo task với pg_cron

Khi pg_cron đã cài và chạy ngon lành, thử tạo task xóa log cũ trong table logs mỗi ngày nhé.

SELECT cron.schedule('Xóa log cũ',
'0 0 * * *',
$$ DELETE FROM logs WHERE created_at < NOW() - INTERVAL '30 days' $$);

Giải thích chút nè:

  • '0 0 * * *' — lịch chạy task (mỗi ngày lúc 0h).
  • DELETE FROM logs ... — SQL query mà cron sẽ chạy.

Xem các task

Để xem tất cả task đang chạy qua pg_cron, dùng:

SELECT * FROM cron.job;

Tắt task

Tắt task bằng lệnh:

SELECT cron.unschedule(jobid);

Trong đó jobid là ID của task. Bạn lấy nó từ bảng cron.job nhé.

Ví dụ hay với pg_cron

Kiểm tra query chạy lâu định kỳ

Tạo task kiểm tra query chạy lâu mỗi 5 phút:

SELECT cron.schedule('Kiểm tra query lâu',
'*/5 * * * *',
$$ SELECT pid, query, state
    FROM pg_stat_activity
    WHERE state = 'active'
        AND now() - query_start > INTERVAL '5 minutes' $$);

Task này sẽ tìm các query chạy hơn 5 phút.

Tích hợp với hệ thống bên ngoài

Cả pg_notify và pg_cron đều có thể tích hợp với hệ thống ngoài như Slack, Telegram hoặc hệ thống monitor (ví dụ Prometheus).

Telegram

Bạn có thể kết hợp pg_notify với bot Telegram để gửi thông báo. Ý tưởng là viết script Python hoặc ngôn ngữ khác, lắng nghe thông báo và gửi lên Telegram.

Ví dụ bot Python đơn giản:

import psycopg2
import telegram

# Kết nối PostgreSQL
conn = psycopg2.connect("dbname=your_database user=your_user")

# Tạo Telegram bot
bot = telegram.Bot(token='your_telegram_bot_token')

# Mở cursor để lắng nghe
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cur = conn.cursor()
cur.execute("LISTEN alerts;")

# Lắng nghe thông báo
print("Đang lắng nghe thông báo...")
while True:
    conn.poll()
    while conn.notifies:
        notify = conn.notifies.pop()
        print("Nhận được thông báo:", notify.payload)
        bot.send_message(chat_id='your_chat_id', text=notify.payload)

Giờ bot của bạn sẽ nhận mọi thông báo gửi qua pg_notify.

Khi nào dùng pg_notify và pg_cron?

Dùng pg_notify cho phản ứng tức thì (ví dụ báo admin khi có deadlock).

Dùng pg_cron cho task định kỳ (kiểm tra query, dọn dữ liệu cũ).

Lưu ý và bẫy thường gặp

pg_notify gửi thông báo ngay lập tức nhưng không lưu lịch sử. Nên tích hợp thêm với file log hoặc hệ thống ngoài.

pg_cron có thể gây tải bất ngờ nếu task chạy quá thường xuyên. Luôn test query kỹ trước khi thêm vào lịch.

Giờ thì bạn đã sẵn sàng tối ưu monitor và tự động hóa quản lý database rồi đó. Triển thôi — cài alert để không chỉ là coder SQL mà còn là DBA xịn sò!

2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Tạo một thông báo đơn giản với `pg_notify`
Tạo một thông báo đơn giản với `pg_notify`
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION