DBAtlas · Veritabanı operasyon atlası

Yavaş yazma (INSERT/UPDATE gecikmesi)

INSERT/UPDATE/DELETE işlemleri beklenenden yavaş. Önce yazmanın neyi beklediğini (commit/redo, lock, disk ya da satır başına ek maliyet) belirleyip adım adım kök nedene iniyoruz.

Yazma neyi bekliyor?

Wait event'lere bakarak darboğazı sınıfla: commit/redo (WAL) senkronizasyonu mu, lock mi, disk yazma gecikmesi mi, yoksa satır başına index/trigger maliyeti mi baskın?

SELECT event, total_waits, ROUND(time_waited/100,1) AS sec_waited
FROM v$system_event
WHERE event IN ('log file sync','log file parallel write','enq: TX - row lock contention','db file sequential read')
ORDER BY time_waited DESC;
  • Commit / redo (WAL sync) bekliyor
  • Lock bekliyor
  • Satır başına ek maliyet (index/trigger) şüphesi
  • Disk yazma gecikmesi yüksek

Commit deseni mi, fsync mi?

Her satırda ayrı commit (autocommit) redo/log senkronizasyonunu satır sayısı kadar tetikler. Aksine commit sayısı makul ama her commit fsync'te bekliyorsa sorun log diskinin gecikmesindedir.

SELECT name, value FROM v$sysstat WHERE name IN ('user commits','redo writes','redo size');
SELECT ROUND(time_waited_micro/GREATEST(total_waits,1)/1000,2) AS ms_per_sync FROM v$system_event WHERE event='log file sync';
  • Autocommit / her satırda commit var
  • Commit log senkronizasyonunda (fsync) bekliyor

Lock'u kim tutuyor?

Yazma bir lock için bekliyorsa: başka bir oturum aynı satırı/index'i tutuyor olabilir, ya da çok sayıda oturum aynı hot row'a yazmaya çalışıyor olabilir.

SELECT s.sid, s.serial#, s.username, s.blocking_session, s.event, s.seconds_in_wait
FROM v$session s WHERE s.blocking_session IS NOT NULL;
  • Başka oturum lock'u tutuyor
  • Çok oturum aynı hot row'a yazıyor

Satır başına ek maliyet nereden?

Her INSERT/UPDATE, tablodaki tüm index'leri de günceller ve varsa trigger/constraint'leri çalıştırır. Aşırı index sayısı ya da ağır trigger, yazmayı ciddi yavaşlatır.

SELECT index_name, uniqueness FROM user_indexes WHERE table_name='T';
SELECT trigger_name, triggering_event FROM user_triggers WHERE table_name='T';
  • Tabloda çok fazla / gereksiz index var
  • Ağır trigger veya constraint maliyeti var

Kök neden: Autocommit / satır başına commit

Her satır için ayrı commit, redo/log senkronizasyonunu satır sayısı kadar tekrarlar. Transaction'ları gruplayarak commit sayısını (dolayısıyla fsync sayısını) dramatik biçimde azaltabilirsin.

Kök neden: Yavaş redo/log diski (fsync gecikmesi)

Her commit, redo/WAL kaydını kalıcı diske yazana (fsync) kadar bekler. Log diski yavaşsa (yüksek yazma gecikmesi, IOPS yetersizliği), her commit bu gecikmeyi öder.

Kök neden: Başka oturum lock'u tutuyor

Yazma, başka bir oturumun tuttuğu satır/index lock'unu bekliyor. Genelde uzun süren ya da commit'i unutulmuş bir transaction engelleyicidir.

Kök neden: Hot row çekişmesi

Çok sayıda oturum aynı satıra (ör. bir sayaç, sıra numarası, bakiye) yazmaya çalışıyor; hepsi aynı lock için sıraya giriyor ve yazma serileşiyor.

Kök neden: Aşırı index maliyeti

Tablodaki her index, her yazmada güncellenir. Çok sayıda ya da kullanılmayan index, INSERT/UPDATE'i doğrudan yavaşlatır.

Kök neden: Ağır trigger / constraint

Yazma başına çalışan trigger veya doğrulanan constraint (özellikle index'siz foreign key kontrolü) her satıra ek maliyet bindirir.

DBAtlas'ta aç →