Każdy z nas chce wiedzieć o problemach zanim nasz serwer padnie albo zacznie utrudniać życie użytkownikom. PostgreSQL daje nam narzędzia do tworzenia powiadomień i uruchamiania zadań: pg_notify i pg_cron. To taki nasz prywatny budzik i scheduler dla bazy danych.
Wyobraź sobie sytuację: masz bazę danych kursu wymiany walut i nagle jeden z procesów zablokował resztę. Zamiast ciągle ręcznie sprawdzać stan bazy, możesz ustawić powiadomienia, żeby być na bieżąco. A do regularnego sprawdzania stanu bazy przyda się pg_cron. Zaraz wszystko ogarniemy.
Szybkie powiadomienia z bazy danych: pg_notify
Zaczynamy od pg_notify. To wbudowana funkcja PostgreSQL, która pozwala wysłać powiadomienie z bazy do konkretnego "kanału". Możesz jej użyć do sygnalizowania zdarzeń, takich jak zakończenie długich zapytań, wykrycie blokad albo innych nietypowych sytuacji.
Składnia pg_notify jest całkiem prosta:
NOTIFY <channel>, <message>;
channel— nazwa kanału, na który wysyłane jest powiadomienie.message— tekst powiadomienia.
Przykład użycia pg_notify. Zróbmy powiadomienie na wypadek wykrycia blokady:
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', 'Blokada w bazie danych!');
END IF;
END $$;
Ten kod sprawdza, czy jest jakaś nieprzyznana blokada i wysyła powiadomienie na kanał alerts.
Żeby nasłuchiwać powiadomień, użyj komendy LISTEN w innym połączeniu:
LISTEN alerts;
Teraz, jeśli pg_notify wyśle wiadomość na kanał alerts, zobaczysz powiadomienie w konsoli.
Przykład:
NOTIFY alerts, 'Hej, tu blokada!';
Na innym połączeniu, gdzie było LISTEN alerts, od razu dostaniesz:
NOTIFY: Hej, tu blokada!
Zastosowanie pg_notify nie kończy się na prostych powiadomieniach. Możesz go połączyć z triggerami, żeby automatycznie informować o dodanych, zmienionych lub usuniętych danych:
Powiadomienie o nowych rekordach
CREATE OR REPLACE FUNCTION notify_new_record()
RETURNS trigger AS $$
BEGIN
PERFORM pg_notify('table_changes', 'Nowy rekord dodany do tabeli!');
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER record_added
AFTER INSERT ON your_table
FOR EACH ROW EXECUTE FUNCTION notify_new_record();
Teraz, jeśli do tabeli your_table zostanie dodany nowy rekord, od razu dostaniesz powiadomienie.
Więcej o triggerach i funkcjach wbudowanych poznasz już za kilka poziomów :P
Typowe błędy i jak ich unikać
Jeśli używasz LISTEN, ale nie widzisz powiadomień, sprawdź:
- Czy pracujesz na tym samym połączeniu, z którego wysyłane są powiadomienia.
- Czy dobrze podałeś nazwę kanału.
- Czy wywołujesz
pg_notifywewnątrz transakcji, która została zatwierdzona (COMMIT).
Scheduler zadań w PostgreSQL: pg_cron
pg_cron to rozszerzenie do PostgreSQL, które pozwala wykonywać zadania według harmonogramu, zupełnie jak klasyczny cron w Linuksie. Na przykład możesz ustawić regularne sprawdzanie blokad albo zbieranie statystyk.
Tworzenie zadań z pg_cron
Gdy pg_cron jest już zainstalowany i gotowy do pracy, stwórzmy zadanie, które codziennie będzie czyścić stare rekordy w tabeli logs.
SELECT cron.schedule('Usuwanie starych logów',
'0 0 * * *',
$$ DELETE FROM logs WHERE created_at < NOW() - INTERVAL '30 days' $$);
Co tu się dzieje:
'0 0 * * *'— to harmonogram wykonania polecenia (codziennie o północy).DELETE FROM logs ...— to SQL, który cron będzie wykonywał.
Podgląd zadań
Żeby zobaczyć wszystkie zadania wykonywane przez pg_cron, użyj:
SELECT * FROM cron.job;
Wyłączanie zadań
Wyłączyć zadanie możesz przez:
SELECT cron.unschedule(jobid);
Gdzie jobid — to identyfikator zadania. Możesz go znaleźć w tabeli cron.job.
Przydatne przykłady z pg_cron
Regularne sprawdzanie aktywności zapytań
Stwórzmy zadanie, które co 5 minut sprawdza długo trwające zapytania:
SELECT cron.schedule('Sprawdzanie długich zapytań',
'*/5 * * * *',
$$ SELECT pid, query, state
FROM pg_stat_activity
WHERE state = 'active'
AND now() - query_start > INTERVAL '5 minutes' $$);
To zadanie szuka zapytań, które trwają dłużej niż 5 minut.
Integracja z zewnętrznymi systemami
Zarówno pg_notify, jak i pg_cron możesz zintegrować z zewnętrznymi systemami, jak Slack, Telegram czy systemy monitoringu (np. Prometheus).
Telegram
Możesz połączyć pg_notify z botem Telegram do wysyłania powiadomień. Główna idea — napisać skrypt w Pythonie lub innym języku, który nasłuchuje powiadomień i wysyła je do Telegrama.
Przykład prostego bota w Pythonie:
import psycopg2
import telegram
# Połączenie z PostgreSQL
conn = psycopg2.connect("dbname=your_database user=your_user")
# Tworzenie bota Telegram
bot = telegram.Bot(token='your_telegram_bot_token')
# Otwieramy cursor do nasłuchiwania
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
cur = conn.cursor()
cur.execute("LISTEN alerts;")
# Nasłuchujemy powiadomień
print("Nasłuchujemy powiadomień...")
while True:
conn.poll()
while conn.notifies:
notify = conn.notifies.pop()
print("Odebrano powiadomienie:", notify.payload)
bot.send_message(chat_id='your_chat_id', text=notify.payload)
Teraz twój bot będzie dostawał powiadomienia wysłane przez pg_notify.
Kiedy używać pg_notify i pg_cron?
Używaj pg_notify do natychmiastowych reakcji (np. powiadom admina o blokadach).
Używaj pg_cron do regularnego wykonywania zadań (sprawdzanie aktywności zapytań, czyszczenie starych danych).
Uwagi i pułapki
pg_notify generuje powiadomienia natychmiast, ale nie przechowuje ich historii. Lepiej zintegrować go z logami plikowymi albo zewnętrznymi systemami.
pg_cron może wywołać nieoczekiwane obciążenie, jeśli zadania są wykonywane zbyt często. Zawsze testuj zapytania przed dodaniem ich do harmonogramu.
Teraz jesteś gotowy, żeby zoptymalizować swój monitoring i zautomatyzować zarządzanie bazą danych. Do dzieła — ustawiaj alerty i bądź nie tylko SQL-programistą, ale prawdziwym DBA!
GO TO FULL VERSION