Audytowanie tabel za pomocą triggerów
Budować ścieżkę audytu za pomocą triggerów AFTER INSERT/UPDATE/DELETE zapisujących dane w tabeli audit_log
Audytowanie tabel za pomocą triggerów to bezpłatna lekcja SQL Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Academy zawiera 4 lekcji w sumie.
Dlaczego audytowanie?
Dzienniki audytowe odpowiadają na pytanie „kto, co i kiedy zmienił”. Są wymagane na potrzeby zgodności z przepisami (HIPAA, SOX, dochodzeń dotyczących prawa do usunięcia danych zgodnie z GDPR) oraz analiz incydentów operacyjnych.
Tabela audytowa
Jedna centralna tabela rejestruje każdą zmianę:
CREATE TABLE audit_log (
id BIGSERIAL PRIMARY KEY,
ts TIMESTAMPTZ NOT NULL DEFAULT NOW(),
user_name TEXT NOT NULL DEFAULT CURRENT_USER,
table_name TEXT NOT NULL,
action TEXT NOT NULL, -- INSERT, UPDATE, DELETE
row_id TEXT,
old_data JSONB,
new_data JSONB
);Funkcja wyzwalacza audytowego
Jedna funkcja, którą można ponownie wykorzystać dla wielu tabel:
CREATE OR REPLACE FUNCTION audit_row()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO audit_log (table_name, action, row_id, old_data, new_data)
VALUES (
TG_TABLE_NAME,
TG_OP,
COALESCE(NEW.id::TEXT, OLD.id::TEXT),
CASE WHEN TG_OP IN ('UPDATE','DELETE') THEN to_jsonb(OLD) END,
CASE WHEN TG_OP IN ('INSERT','UPDATE') THEN to_jsonb(NEW) END
);
RETURN COALESCE(NEW, OLD);
END;
$$ LANGUAGE plpgsql;Dołączanie do tabel
Wyzwalacz dla AFTER INSERT/UPDATE/DELETE:
CREATE TRIGGER trg_audit_users
AFTER INSERT OR UPDATE OR DELETE ON users
FOR EACH ROW EXECUTE FUNCTION audit_row();to_jsonb(NEW)
Sztuczka z to_jsonb przechwytuje cały wiersz w sposób ogólny — bez kodu dla poszczególnych kolumn. Działa dla każdej tabeli zawierającej kolumnę id.
Śledzenie użytkownika
Jeśli aplikacja działa jako pojedynczy użytkownik bazy danych, CURRENT_USER nie wystarcza. Należy przekazać użytkownika aplikacji za pomocą sesyjnego GUC:
-- App sets:
SET LOCAL app.user_id = '42';
-- Trigger reads:
INSERT INTO audit_log (... actor_id ...) VALUES (..., current_setting('app.user_id', true)::BIGINT);Audytowanie określonych kolumn
Do wybiórczego audytowania należy użyć klauzuli WHEN wyzwalacza:
CREATE TRIGGER trg_audit_role_change
AFTER UPDATE OF role ON users
FOR EACH ROW WHEN (OLD.role IS DISTINCT FROM NEW.role)
EXECUTE FUNCTION audit_role_change();Oddzielne tabele audytowe dla każdej tabeli
Alternatywą jest jedna tabela audytowa dla każdej rzeczywistej tabeli (np. users_audit) z tym samym schematem + metadanymi audytowymi. Ułatwia to wykonywanie zapytań, ale wymaga utrzymywania większej ilości DDL.
Audytowanie wyłącznie zmian
Przechowuj tylko zmienione kolumny:
INSERT INTO audit_log (table_name, action, changes)
VALUES (
TG_TABLE_NAME, TG_OP,
(SELECT jsonb_object_agg(key, value)
FROM jsonb_each(to_jsonb(NEW))
WHERE NEW.* IS DISTINCT FROM OLD.* AND to_jsonb(NEW)->key IS DISTINCT FROM to_jsonb(OLD)->key)
);Wydajność tabeli audytowej
Tabela audytowa szybko rośnie w obciążonych systemach. Należy ją partycjonować według czasu:
CREATE TABLE audit_log (...) PARTITION BY RANGE (ts);
CREATE TABLE audit_log_2024_q1 PARTITION OF audit_log
FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');Kompromis wydajności
Każde wstawienie, zaktualizowanie lub usunięcie zapisuje teraz dodatkowy wiersz. W przypadku tabel z bardzo dużą liczbą zapisów może to podwoić operacje I/O. Należy przeprowadzić testy, monitorować system i zdecydować, czy ten kompromis się opłaca.
Kiedy NIE używać wyzwalaczy bazy danych
Jeśli potrzebna jest integracja z magistralą zdarzeń, należy kolejkować zdarzenia za pomocą NOTIFY lub LISTEN albo użyć replikacji logicznej / narzędzi CDC (Debezium) zamiast wyzwalaczy.
Podsumowanie
Wyzwalacze audytowe to najprostszy sposób rejestrowania historii.
- Jedna ogólna funkcja z to_jsonb(NEW/OLD)
- Dołącz ją do każdej audytowanej tabeli
- Partycjonuj tabele audytowe według czasu
- Jawnie śledź użytkownika aplikacji za pomocą GUC
Szybki sprawdzian
Jak wewnątrz funkcji wyzwalacza audytowego ogólnie przechwycić nowy wiersz jako JSONB?
Często zadawane pytania
Czy lekcja „Audytowanie tabel za pomocą triggerów” jest bezpłatna?
Tak — pełny tekst „Audytowanie tabel za pomocą triggerów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Academy, przejdź na CoddyKit PRO. Kurs SQL Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Audytowanie tabel za pomocą triggerów”?
Budować ścieżkę audytu za pomocą triggerów AFTER INSERT/UPDATE/DELETE zapisujących dane w tabeli audit_log Ćwiczysz SQL Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć SQL Academy?
Nie wymagamy żadnego doświadczenia. SQL Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Audytowanie tabel za pomocą triggerów”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji SQL Academy?
Tak. Każda lekcja SQL Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Budowa triggerów: BEFORE/AFTER, FOR EACH ROW
- Podstawy funkcji PL/pgSQL
- Bloki DO i kod anonimowy
- Audytowanie tabel za pomocą triggerów