Gereksinimler ve Ön Hazırlık
Bu rehberi uygulamak için sisteminizde kurulu olması gereken temel araçlar şunlardır:
- Veritabanı Yönetim Sistemi: PostgreSQL 16+ veya MySQL 8.4+ sürümü (JSON veri tipi desteği önerilir).
- Programlama Dili: Uygulama katmanı için modern bir dil (Örn: Python, PHP veya Node.js).
- Veritabanı Sürücüsü: Güvenli sorgu çalıştırmayı destekleyen bir kütüphane (PDO, SQLAlchemy veya Prisma).
- Temel SQL Bilgisi: Tablo oluşturma, kısıtlamalar (constraints) ve transaction yönetimi.
Adım 1: Günlükleme Tablosu Tasarımı
Veri kayıt günlükleme için kullanılacak tablo yapısı, arama performansını artıracak şekilde tasarlanmalıdır. Geleneksel sütun yapısının yanı sıra, esneklik sağlamak adına JSONB (PostgreSQL) veya JSON (MySQL) veri tiplerini tercih etmelisiniz.
CREATE TABLE application_logs (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
log_level VARCHAR(10) NOT NULL,
message TEXT NOT NULL,
context JSON,
user_id INT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX(log_level),
INDEX(created_at)
);
Bu tablo yapısı, log seviyelerine (INFO, ERROR, DEBUG) göre hızlı filtreleme yapmanıza olanak tanır. context sütunu, hatanın oluştuğu anki değişken değerlerini veya detaylı hata kodlarını saklamak için kullanılır.
Adım 2: Uygulama Katmanından Veritabanına Log Gönderme
Uygulamanızda doğrudan SQL sorguları yazmak yerine, bir "Logger" sınıfı veya fonksiyonu oluşturmak, kodunuzun bakımını kolaylaştırır. SQL Injection saldırılarını önlemek için mutlaka parametreli sorgular (prepared statements) kullanmalısınız.
def log_to_db(cursor, level, message, context=None):
sql = "INSERT INTO application_logs (log_level, message, context) VALUES (%s, %s, %s)"
cursor.execute(sql, (level, message, context))
# Bağlantıyı commit etmeyi unutmayın
Yukarıdaki örnekte, cursor.execute metodunun parametreleri ayrıştırması, veritabanı güvenliğinizi doğrudan koruma altına alır. Asla kullanıcıdan gelen veriyi doğrudan SQL sorgusunun içine birleştirmeyin.
Adım 3: Veritabanı Triggerları ile Otomatik Günlükleme
Bazı durumlarda, veritabanındaki kritik değişiklikleri (örneğin bir kullanıcının bakiyesinin güncellenmesi) uygulama katmanından bağımsız olarak izlemek istersiniz. Bu noktada veritabanı tetikleyicileri (triggers) devreye girer.
CREATE TRIGGER after_user_update
AFTER UPDATE ON users
FOR EACH ROW
BEGIN
INSERT INTO application_logs (log_level, message, context)
VALUES ('INFO', 'Kullanıcı verisi güncellendi', JSON_OBJECT('user_id', OLD.id, 'old_email', OLD.email));
END;
Triggerlar, veri bütünlüğünü sağlamak için mükemmeldir. Ancak, çok yoğun trafik alan tablolarda trigger kullanımı veritabanı performansını etkileyebilir. Bu nedenle, sadece kritik tablolar için tercih edilmelidir.
Adım 4: Performans ve Optimizasyon Stratejileri
Veritabanı günlükleme işlemleri, ana uygulama akışınızı yavaşlatmamalıdır. Büyük ölçekli sistemlerde günlükleri senkron (eşzamanlı) olarak veritabanına yazmak yerine, asenkron bir kuyruk yapısı kullanmak çok daha verimlidir.
| Yöntem | Avantajı | Dezavantajı |
|---|---|---|
| Senkron Yazma | Veri tutarlılığı yüksektir. | Uygulama hızı düşebilir. |
| Asenkron Kuyruk | Yüksek performans sağlar. | Karmaşık yapı gerektirir. |
| Dosya Tabanlı Log | Veritabanını yormaz. | Sorgulama zordur. |
Adım 5: Güvenli ve Etik Günlükleme
Loglama yaparken kişisel verilerin korunması (KVKK/GDPR) yasalar gereği zorunludur. Kullanıcı şifreleri, kredi kartı numaraları veya kişisel kimlik verileri asla log dosyalarına veya veritabanı log tablolarına açık metin olarak kaydedilmemelidir.
Kritik Güvenlik Uyarısı: Günlükleme veritabanına yazılan verileri mutlaka maskeleyin. Şifreler, tokenlar ve hassas kişisel veriler log tablosuna girmeden önce temizlenmelidir. Aksi takdirde, veritabanı sızıntısı durumunda log tabloları en büyük veri ihlali kaynağı olur.
# Hassas veriyi maskeleme örneği
def sanitize_log(data):
if 'password' in data:
data['password'] = '***MASKED***'
return data
Sıkça Sorulan Sorular
Log tabloları çok büyürse ne yapmalıyım?
Log tabloları zamanla milyonlarca satıra ulaşabilir. "Partitioning" (bölümleme) yöntemini kullanarak verileri aylık veya haftalık parçalara ayırabilir, eski logları arşivleyerek veritabanından silebilirsiniz.
Loglama uygulamamı yavaşlatır mı?
Evet, her işlemde veritabanına yazmak ek bir I/O yükü getirir. Bu yüzden Redis veya RabbitMQ gibi bir mesaj kuyruğu kullanarak logları arka planda işlemek en iyi pratiktir.
Hangi olayları loglamalıyım?
Başarısız giriş denemeleri, kritik veri değişiklikleri, sistem hataları ve yetki yükseltme işlemleri mutlaka loglanmalıdır.
Veritabanı günlükleri ile uygulama logları aynı mı?
Hayır. Uygulama logları genellikle dosya sistemine (örneğin .log dosyaları) yazılırken, veritabanı günlükleri (Audit Logs) veritabanı içindeki tablolarda tutulur. İkisinin de kullanım amacı farklıdır.
Log verilerini nasıl temizlemeliyim?
Otomatik bir "Cron Job" veya veritabanı zamanlanmış görevi ile 90 günden eski logları silen veya başka bir soğuk depolama alanına (S3 gibi) aktaran bir script çalıştırmalısınız.
İleri Düzey Senaryo: Log Verilerinin Bölümlenmesi (Partitioning)
Veritabanı günlükleme sistemlerinde en büyük zorluk, milyonlarca satıra ulaşan log tablolarının sorgu performansını düşürmesidir. Büyük ölçekli sistemlerde, Partitioning (Bölümleme) stratejisi kullanarak verileri zamana göre fiziksel olarak ayırmak, hem okuma hızını artırır hem de eski verilerin temizlenmesini (archiving) kolaylaştırır.
Aşağıdaki SQL örneği, PostgreSQL üzerinde aylık bazda bölümleme yapılmış bir log tablosu yapısını göstermektedir:
CREATE TABLE system_logs (
log_id SERIAL,
event_time TIMESTAMP NOT NULL,
log_level VARCHAR(10),
message TEXT,
PRIMARY KEY (log_id, event_time)
) PARTITION BY RANGE (event_time);
-- Ocak ayı için bölüm oluşturma
CREATE TABLE system_logs_2023_01 PARTITION OF system_logs
FOR VALUES FROM ('2023-01-01') TO ('2023-02-01');
Bu yöntem sayesinde, eski bir aya ait logları silmek istediğinizde DELETE komutuyla tüm tabloyu taramak yerine, sadece ilgili bölümü (partition) DROP TABLE komutuyla saniyeler içinde kaldırabilirsiniz.
Hata Ayıklama (Debugging) İçin Log Korelasyonu
Dağıtık sistemlerde bir hata oluştuğunda, bu hatanın hangi kullanıcıdan veya hangi işlemden kaynaklandığını bulmak zordur. Bunun için Correlation ID (İzleme Kimliği) kullanmak kritik bir pratiktir. Uygulama katmanından veritabanına gönderilen her log satırına, o isteğe özel benzersiz bir ID eklemelisiniz.
Örnek bir uygulama içi loglama akışı şu şekilde olmalıdır:
- Kullanıcı isteği geldiğinde bir
request_id(UUID) oluşturun. - Veritabanı işlemleri sırasında bu ID'yi her log kaydına ekleyin.
- Hata anında, veritabanında şu sorguyu çalıştırarak tüm süreci izleyin:
SELECT * FROM system_logs
WHERE correlation_id = 'a1b2c3d4-e5f6-7890-abcd-1234567890ab'
ORDER BY event_time ASC;
Bu yöntem, karmaşık mikro hizmet mimarilerinde bile veritabanı seviyesinde "iz sürmenizi" kolaylaştırır. Loglarınızı yapılandırırken JSONB veri tipini kullanarak esnek meta veriler (kullanıcı IP'si, tarayıcı bilgisi, uygulama versiyonu) saklamanız, hata ayıklama sürecini %80 oranında hızlandıracaktır.
Profesyonel İpucu: Log tablolarınızda asla "SELECT *" kullanmayın. Log verileri genellikle büyük hacimli olduğundan, her zaman belirli sütunları (örn:event_time,log_level) seçerek sorgu maliyetini düşürün.
Sonuç
Sql & veritabanı ile uygulamalar için veri kayıt günlükleme, sisteminizin sağlığını izlemek ve olası kriz anlarında hızlı müdahale edebilmek için vazgeçilmez bir yetenektir. Bu rehberde öğrendiğiniz tablo tasarımı, trigger kullanımı ve güvenlik önlemleri, profesyonel bir loglama altyapısının temel taşlarıdır.
Bir sonraki adım olarak, log verilerinizi görselleştirmek için Grafana veya ELK Stack (Elasticsearch, Logstash, Kibana) gibi araçları veritabanınıza bağlamayı deneyebilirsiniz. Bu sayede veritabanındaki logları anlamlı grafiklere dönüştürerek sisteminizin performansını gerçek zamanlı takip edebilirsiniz.
Sorumluluk Reddi: Bu rehberde paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanmadan önce mutlaka kendi güvenlik testlerinizi yapın ve veritabanı erişim izinlerini (RBAC) en düşük yetki prensibine göre yapılandırın.


Yorumlar (0)
Yorum Yaz