Təsəvvür elə ki, sən böyük bir verilənlər bazasının administratorusan. Birdən kimsə vacib məlumatı cədvəldən silir və hamı qışqırır: "Bunu kim elədi?!". Belə situasiyalardan qaçmaq üçün verilənlər bazası dəyişiklikləri qeyd etməyə və baş verənləri izləməyə imkan verir. Bütün bunlar log-lama və audit vasitəsilə edilir.
- Dəyişikliklərin log-lanması baş verənlərin tarixçəsini saxlamağa imkan verir: hansı qeyd dəyişdi, necə və nə vaxt.
- Data auditi daha dərin yoxlama üçün istifadə olunur, təkcə dəyişiklikləri yox, həm də onları başladan istifadəçi barədə məlumatı da qeyd edir.
Artıq "nəyə görə" sualını başa düşdün, indi isə gəlin "necə" sualına baxaq.
Log-lar üçün cədvəlin yaradılması
Trigger-ləri qurmağa başlamazdan əvvəl, dəyişikliklərin log-lanması üçün bir cədvələ ehtiyacımız var. Məsələn belə:
-- Dəyişikliklərin log-lanması üçün cədvəl yaradırıq
CREATE TABLE change_logs (
log_id SERIAL PRIMARY KEY, -- Qeyd üçün unikal identifikator
table_name TEXT NOT NULL, -- Dəyişiklik olan cədvəlin adı
operation TEXT NOT NULL, -- Əməliyyat tipi: INSERT, UPDATE, DELETE
change_time TIMESTAMP DEFAULT NOW(), -- Dəyişiklik vaxtı
old_data JSONB, -- Dəyişiklikdən əvvəlki data (UPDATE/DELETE üçün)
new_data JSONB -- Dəyişiklikdən sonrakı data (INSERT/UPDATE üçün)
);
Bura nə baş verir?
log_id— log üçün hər bir qeyd üçün unikal identifikator.table_name— hansı cədvəlin dəyişdiyini qeyd edəcəyik.operation— əməliyyat tipi:INSERT,UPDATEvə yaDELETE.change_time— dəyişikliyin dəqiq vaxtını qeyd edir.old_datavənew_data— dəyişiklikdən əvvəl və sonra olan data, JSON formatında.
Trigger vasitəsilə dəyişikliklərin log-lanması
Artıq log cədvəlimiz var, indi isə məsələn, students cədvəli üçün trigger yaradaq. O, bütün dəyişiklikləri qeyd edəcək: yeni tələbə əlavə olunanda, yenilənəndə və ya silinəndə. Bunu belə edəcəyik:
- PL/pgSQL-də log cədvəlinə qeyd əlavə edən funksiya yazacağıq.
studentscədvəli üçün trigger yaradacağıq.
Funksiya əməliyyat barədə məlumatı (INSERT, UPDATE, DELETE) və dəyişən datanı (OLD və NEW) alacaq.
-- Dəyişiklikləri log cədvəlinə yazmaq üçün funksiya
CREATE OR REPLACE FUNCTION log_student_changes()
RETURNS TRIGGER AS $$
BEGIN
-- INSERT əməliyyatının log-lanması
IF TG_OP = 'INSERT' THEN
INSERT INTO change_logs (table_name, operation, new_data)
VALUES ('students', 'INSERT', row_to_json(NEW));
-- DELETE əməliyyatının log-lanması
ELSIF TG_OP = 'DELETE' THEN
INSERT INTO change_logs (table_name, operation, old_data)
VALUES ('students', 'DELETE', row_to_json(OLD));
-- UPDATE əməliyyatının log-lanması
ELSIF TG_OP = 'UPDATE' THEN
INSERT INTO change_logs (table_name, operation, old_data, new_data)
VALUES ('students', 'UPDATE', row_to_json(OLD), row_to_json(NEW));
END IF;
RETURN NULL; -- NULL qaytarırıq, çünki bu AFTER-trigger-dir
END;
$$ LANGUAGE plpgsql;
Bura:
TG_OP— cari əməliyyatı saxlayan xüsusi dəyişən:INSERT,UPDATE,DELETE.row_to_json(OLD)vərow_to_json(NEW)— sətrin datalarını rahat saxlamaq üçün JSON formatına çevirir.RETURN NULL— çünki buAFTER-trigger-dir, dəyişilmiş datanı qaytarmamalıdır.
İndi funksiyamızı students cədvəlinə bağlayaq.
-- Dəyişikliklərin log-lanması üçün trigger yaradırıq
CREATE TRIGGER students_log_trigger
AFTER INSERT OR UPDATE OR DELETE ON students
FOR EACH ROW
EXECUTE FUNCTION log_student_changes();
Bura nə baş verir?
AFTER INSERT OR UPDATE OR DELETE— triggerstudentscədvəlində göstərilən əməliyyatlardan sonra işləyir.FOR EACH ROW— trigger hər dəyişən sətr üçün işləyir.EXECUTE FUNCTION log_student_changes()— log-lama funksiyamızı çağırır.
Trigger-i test edirik
İndi trigger-in necə işlədiyini yoxlayaq.
- Yeni qeyd əlavə etmək
INSERT INTO students (name, age, grade)
VALUES ('Otto Lin', 20, 'A');
Log cədvəlində nə yazılıb baxaq:
SELECT * FROM change_logs;
Nümunə nəticə:
| log_id | table_name | operation | change_time | old_data | new_data |
|---|---|---|---|---|---|
| 1 | students | INSERT | 2023-10-10 12:00:00 | NULL | {"name": "Otto Lin", "age": 20, ...} |
- Qeydi yeniləmək
UPDATE students
SET grade = 'B'
WHERE name = 'Otto Lin';
Yenə log cədvəlinə baxaq:
SELECT * FROM change_logs ORDER BY change_time DESC;
Nəticə:
| log_id | table_name | operation | change_time | old_data | new_data |
|---|---|---|---|---|---|
| 2 | students | UPDATE | 2023-10-10 12:05:00 | {"name": "Otto Lin", "age": ...} | {"name": "Otto Lin", "age": ..., ...} |
- Qeydi silmək
DELETE FROM students
WHERE name = 'Otto Lin';
Yenə log-a baxaq:
| log_id | table_name | operation | change_time | old_data | new_data |
|---|---|---|---|---|---|
| 3 | students | DELETE | 2023-10-10 12:10:00 | {"name": "Otto Lin", "age": ...} | NULL |
Real istifadə nümunələri
- Kritik cədvəllərdə əməliyyatların log-lanması: məsələn, bank hesabları olan cədvəl bütün dəyişikliklərin qeyd olunmasını tələb edir ki, fırıldaqçılığın qarşısı alınsın.
- Sistemin auditi: sən normativ uyğunluq və ya istifadəçi aktivliyinin analizi üçün qeydləri saxlaya bilərsən.
- Data bərpasının təmin olunması: kimsə təsadüfən datanı silsə, log cədvəlindən onu bərpa edə bilərsən.
Xüsusiyyətlər və gizli tələlər
Trigger-lərlə log-lama quranda performansı nəzərə almaq vacibdir. Əgər trigger çox tez-tez işləyirsə, bu, verilənlər bazasına əlavə yük verə bilər. Ona görə də:
- Log-lamanı yalnız kritik cədvəllərdə istifadə et.
- Əgər log-ların həcmi çox böyüyürsə, arxivləşdirmə strategiyası hazırla.
Trigger-lər gitara simi kimidir: düzgün tənzimləmə tələb edir, amma gündəlik işləri avtomatlaşdırır və dataya nəzarəti təmin edir.
GO TO FULL VERSION