Blog
Mert Özen'in yazılım geliştirme, backend, frontend ve DevOps üzerine blog yazıları.
Veritabanını Ne Zaman ve Nasıl Ölçeklemeli? Ölçüm, Darboğaz ve Scaling Merdiveni
Veritabanını ölçeklemeye p50/p95/p99 latency, throughput ve aktif session'ların neyi beklediği ölçülmeden karar verilmez; çoğu zaman ilk basamak sorgu ve index'tir. Bookstore'un sipariş geçmişi sorgusu 64 istemcide 187 istek/sn'de tıkanıyordu, tek bir index p99'u 653 ms'den 5,6 ms'ye indirdi. Little's Law, pg_stat_statements ve DMV'lerle darboğaz bulmak, scaling merdiveni, kapasite hesabı ve SLO.
Connection Pooling Derinlemesine: ADO.NET Pool'u, Pool Exhaustion, Npgsql ve PgBouncer
"Max pool size was reached" hatası neredeyse hiçbir zaman pool'un küçüklüğünden değil, geri dönmeyen connection'lardan gelir; çözüm sızıntıyı bulmak ve instance × pool × Max Pool Size bütçesini hesaplamaktır. SqlClient pool key'i ve counter'ları, Application Name ile 50 pool'a bölünen fragmentation, PostgreSQL'de 53300 hatası, PgBouncer'ın 250 istemciyi 20 connection'la 5,5 kat throughput'la taşıması, transaction mode'da sızan SET ve max_prepared_statements.
Büyük Tablolarla Yaşamak: Batch'li DELETE/UPDATE, Arşivleme, Online Index ve Online Şema Değişikliği
Büyük tabloda eski veriyi silmenin güvenli yolu tek dev DELETE değil, kendi transaction'ında checkpoint yazan keyset tabanlı küçük batch'lerdir. Tek transaction lock escalation ile müşteri okumasını düşürdü, log'u 200 MB'a büyüttü ve replica'yı 22 MB geride bıraktı; batch'li job aynı işi okumaları hiç bloklamadan, kesilince kaldığı yerden yaptı. Resumable index, CREATE INDEX CONCURRENTLY ve tabloyu yeniden yazan ALTER'lar.
Veritabanı Replication'ı: Physical ve Logical, Sync ve Async, Always On ve PostgreSQL Streaming Replication
Replication, commit log'unu başka bir sunucuya taşıyıp yeniden uygulamaktır; commit'in replica'yı bekleyip beklemediği hem kaybedilebilecek veriyi (RPO) hem kullanılabilirliği belirler. Lab'da sync commit throughput'u %37 düşürdü, tek sync replica düşünce yazmalar durdu ve iptal edilen INSERT yine de commit edilmiş çıktı. Streaming replication, lag ölçümü, log shipping, Always On, diski dolduran replication slot ve logical replication.
High Availability ve Failover: RPO/RTO, Listener, Patroni ve Uygulamanın Failover'a Dayanması
Uygulama failover'a ancak idempotent yazma ve failover'ı bekleyen bir retry ile dayanır; async replica ise kayıpsız değildir. Lab'da async replica ile 50 sipariş kayboldu; varsayılan EF Core retry'ı "No suitable host was found" hatasını tekrar denemediği için 98 sipariş düştü, genişletilmiş strategy ve Host Recheck Seconds=1 ile sıfır hata ve sıfır çift kayıt. RPO/RTO, HA ve DR, AG listener, Patroni ve SqlClient ConnectRetryCount.
.NET'te Read/Write Splitting: Read Replica'ya Yönlendirmek ve Read-Your-Writes Sorunu
Okumaları replica'ya taşımak için iki context yetmez; replica'nın geride olduğu anları bilen bir router gerekir. Lab'da lag'i sıfır görünen replica'dan okuyan müşterilerin 1.000 siparişin 4'ünü, replay durunca 300'ün 300'ünü göremediğini ölçtük; lag eşiği ve kullanıcının son yazmasının LSN'ine bakan router ile kaçan sipariş sıfır. Npgsql prefer-standby, SQL Server read-only routing ve hot standby conflict.
PostgreSQL'de Partitioning: Range, List, Hash, Partition Pruning ve Attach/Detach ile Arşiv
PostgreSQL'de partitioning sorguyu kendiliğinden hızlandırmaz, ama arşivi ve bakımı kolaylaştırır. Lab'da partition key'i kullanmayan "Siparişlerim" sorgusu 50 aylık partition'da 7 kat fazla buffer okudu, 1.522 günlük partition'da yalnız planlaması 49 ms sürdü; buna karşılık on ayı DETACH CONCURRENTLY ile pgbench yükü altında, ay başına 40 ms'nin altında ve hatasız arşive taşıdık. Range, list, hash, pruning ve PostgreSQL 18'in ANALYZE ONLY'si.
SQL Server'da Partitioning: Partition Function, Scheme, Aligned Index, Partition Elimination ve SWITCH
SQL Server'da partitioning'in asıl kazancı SWITCH ile milisaniyede arşivlemek; sorgu kazancı ise ancak partition elimination çalışırsa gelir. Lab'da on bir ayı ay başına 10 ms'nin altında arşive taşıdık; buna karşılık AddWithValue(DateTime), Scale = 0 ve EF Core'un datetime2(7) parametreleri datetime2(0) kolonda elimination'ı kapattı ve 52 partition'ın hepsi okundu. RANGE LEFT/RIGHT, aligned index, SPLIT/MERGE maliyeti ve LOCK_ESCALATION = AUTO.
Sharding'e Giriş: Shard Key, Uygulama Seviyesinde Sharding, Citus ve Distributed SQL
Sharding yazma ölçeğini ve veri boyutunu çözer, ama tek sunucuda bedava olan global ID'yi, cross-shard sorguyu ve transaction'ı pahalı hâle getirir. Lab'da iki shard aynı order_id'yi üretti ve her shard'ın ilk 10'unu birleştiren "çok satanlar" listesi doğru listeyle hiç örtüşmedi; doğru sonuç kısmi toplamlardan geldi. .NET'te bucket tabanlı IShardResolver, shard key seçimi, Citus'ta co-location ve distributed SQL.
Uçtan Uca: Bookstore'u 10 Kat Büyümeye Hazırlamak — Ölç, Karar Ver, Uygula, Doğrula
Bookstore'u 10 kat büyümeye hazırlamak sharding değil; index, connection bütçesi, arşiv, read replica ve partitioning'in ölçülerek sırayla eklenmesi. Kampanya yükünde "Siparişlerim" p99'u 4,0 ms kaldı (hedef 50 ms); yük altında primary öldürülüp replica promote edildiğinde yazmalar 7,1 saniye durdu, ama hiçbir istek hata vermedi ve onaylanmış 3.970 siparişin hepsi korundu. Basamakların kazancı ve bedeli, ADR, failover ve restore tatbikatı, kontrol listesi.