MongoDB'de write concern bir yazmanın kaç üye tarafından ve hangi kalıcılık düzeyinde onaylanacağını, read concern bir okumanın ne kadar kalıcı ve tutarlı veri döndüreceğini, read preference ise okumanın replica set'in hangi üyesine gideceğini belirler. Replica set ve sharded kümelerde varsayılan yazma onayı çoğu durumda { w: "majority" }, varsayılan okuma ise primary üzerinden ve "local" read concern ile yapılır. Bu üç ayarı birlikte seçerek tutarlılık, gecikme ve erişilebilirlik arasında denge kurarsınız.
Bu yazıda her bir ayarın seçeneklerini, "çoğunluk" sayısının nasıl hesaplandığını, arbiter içeren kümelerdeki tuzakları, wtimeout davranışını, read concern seviyelerini ve read preference modlarını örneklerle anlatıyoruz. Replica set kurulumunu henüz yapmadıysanız önce MongoDB replica set kurulumu yazısını okuyun. Serinin diğer yazıları MongoDB öğrenme rehberinde listelenir.
| Ayar | Neyi belirler | Tipik değer |
|---|---|---|
| Write concern | Yazmanın kaç üyede ve diskte onaylanacağı | w: majority |
| Read concern | Okunan verinin kalıcılık ve yalıtım düzeyi | local veya majority |
| Read preference | Okumanın hangi üyeye yönlendirileceği | primary |
Write Concern: w, j ve wtimeout

Write concern üç alandan oluşan bir belgedir: w, j ve wtimeout. w yazmanın kaç mongod örneğine ya da hangi etiketli üyelere ulaştığının onaylanmasını ister. j yazmanın diskteki journal'a yazıldığının onaylanmasını ister. wtimeout ise onayı sonsuza kadar beklememek için milisaniye cinsinden bir süre sınırı koyar. Bir yazma işlemine write concern'i seçenek olarak verirsiniz:
db.siparisler.insertOne(
{ musteri: "ayse", tutar: 250 },
{ writeConcern: { w: "majority", j: true, wtimeout: 5000 } }
)Yazma başarılı olduğunda belgelerdeki insertOne yanıtı acknowledged: true ve insertedId alanlarını içerir. Write concern'in fark yarattığı nokta, bu yanıtın ne zaman döndüğüdür.
w değerleri
w: "majority": Hesaplanan çoğunluk kadar veri tutan ve oy veren üyenin değişikliği kendi oplog'una kalıcı olarak yazdığının onaylanmasını ister. Çoğu kurulumda varsayılan budur. Gizli (hidden), gecikmeli (delayed) ve priority 0 üyeler oy hakları varsa bu onaya katkı verebilir; gecikmeli bir üye ancak yapılandırılansecondaryDelaySecssüresi dolduktan sonra onay verir.w: 1: Yalnızca standalone sunucunun veya primary'nin onayını ister. Primary, yazma secondary'lere ulaşmadan geri çekilirse bu yazma geri alınabilir (rollback).w: 0: Hiç onay istemez; yine de soket ve ağ hataları uygulamaya bildirilebilir. Aynı andaj: trueverirsenizj: truebaskın gelir ve primary'den onay istenir.w: 2,w: 3gibi sayılar: Primary ile birlikte gereken sayıda veri tutan üyenin onayını ister. Bu üyelerin oy veren üye olması gerekmez. Üç üyeli bir kümedew: 3tüm üyeleri bekler.- Özel bir ad:
settings.getLastErrorModesiçinde tanımlanan, etiketlere dayalı bir yazma kuralıdır ve örneğin farklı veri merkezlerinden onay istemek için kullanılır.
Çoğunluk Nasıl Hesaplanır? Arbiter Tuzağı
"majority" için gereken üye sayısı iki değerden küçük olanıdır: arbiter'lar dahil tüm oy veren üyelerin çoğunluğu ve veri tutan oy veren üyelerin toplam sayısı. rs.status() çıktısındaki writeMajorityCount alanı bu hesaplanmış değeri doğrudan gösterir.
| Düzen | Oy veren üyelerin çoğunluğu | Veri tutan oy veren üye | Hesaplanan çoğunluk |
|---|---|---|---|
| Primary + 2 secondary (PSS) | 2 | 3 | 2 |
| Primary + secondary + arbiter (PSA) | 2 | 2 | 2 |
Tablo ilk bakışta aynı sonucu veriyor gibi görünür ama anlamları çok farklıdır. PSS düzeninde çoğunluk için primary ve herhangi bir secondary yeterlidir; bir secondary kapansa bile yazmalar onaylanır. PSA düzeninde arbiter veri tutmadığı için iki onayın ikisi de veri tutan üyelerden gelmek zorundadır. Secondary kapandığında "majority" yazmaları zaman aşımına uğrar ya da hiç onaylanmaz. Belgeler bu nedenle mümkünse arbiter yerine veri tutan bir üye kullanmanızı önerir.
Arbiter içeren kümeler için örtük varsayılan da değişir. Oy veren çoğunluk, oy veren üye sayısının yarısının aşağı yuvarlanıp bir eklenmesiyle bulunur. Arbiter varsa ve veri tutan üye sayısı bu çoğunluktan büyük değilse örtük varsayılan write concern { w: 1 } olur; diğer tüm durumlarda { w: "majority" } olur. Belgelerdeki iki örnek bunu netleştirir:
| Veri tutan | Arbiter | Oy veren | Oy çoğunluğu | Örtük varsayılan |
|---|---|---|---|---|
| 2 | 1 | 3 | 2 | w: 1 |
| 4 | 1 | 5 | 3 | w: majority |
j Seçeneği ve Journal
j: true, w ile belirtilen üyelerin yazmayı diskteki journal'a kaydettiğinin onaylanmasını ister ve anında bir journal eşitlemesine neden olur. Belgeler, tek başına j: true değerinin primary failover kaynaklı geri almaya karşı garanti vermediğini vurgular; dayanıklılık için çoğunluk onayı da gerekir.
j belirtilmediğinde w: "majority" davranışını replica set yapılandırmasındaki writeConcernMajorityJournalDefault ayarı belirler. Bu ayar varsayılan olarak true olduğundan çoğunluk yazmaları pratikte j: true gibi diske eşitlenmiş olarak onaylanır. w: 1 veya sayısal değerlerde ise j verilmemişse onay bellekteki yazmadan sonra gelir. Journal kapalı çalışan bir mongod örneğine j: true göndermek hata üretir.
wtimeout Ne Yapar, Ne Yapmaz?
wtimeout, yazma primary'de başarıyla uygulandıktan sonra yeterli sayıda üyeye yayılması için beklenecek süredir; w değeri 1 veya daha küçükse hiç uygulanmaz. Süre dolarsa MongoDB bir write concern hatası döndürür. Belgelerdeki insertOne örneğinde bu hata kodu 64 ve waiting for replication timed out mesajıyla gelir.
Burada en sık yanlış anlaşılan nokta şudur: zaman aşımı yazmayı geri almaz. Primary'de yapılan değişiklik yerinde kalır ve büyük olasılıkla birazdan diğer üyelere de ulaşır. Uygulamanız bu hatayı "yazma olmadı" diye yorumlayıp işlemi tekrarlarsa aynı kaydı iki kez eklemeye çalışabilir; bu da benzersiz bir indeks varsa E11000 duplicate key hatasına yol açar. wtimeout hiç verilmezse ve istenen onay düzeyine ulaşılamıyorsa yazma süresiz bekler; 0 değeri de seçeneği hiç vermemekle aynıdır. Primary üzerindeki işlemin kendisine süre koymak için ise maxTimeMS() kullanılır.
try {
db.siparisler.insertOne(
{ musteri: "mehmet", tutar: 90 },
{ writeConcern: { w: "majority", wtimeout: 2000 } }
)
} catch (e) {
// write concern hatası: veri primary'de yazılmış olabilir, körü körüne tekrar etmeyin
print(e)
}MongoDB 8.0 Sonrası: Çoğunluk Onayı ve Secondary Okumaları
Belgelere göre MongoDB 8.0'dan itibaren { w: "majority" } yazmaları, veri tutan üyelerin çoğunluğu oplog girdisini kalıcı olarak yazdığında onaylanır; üyeler değişikliği daha sonra eşzamansız olarak uygular. Önceki sürümler onay vermeden önce uygulamanın bitmesini beklerdi. Bunun pratik sonucu şudur: onaydan hemen sonra bir secondary'den okuma yaparsanız, o secondary değişikliği henüz uygulamamış olabilir. Secondary'lerden okuyup kendi yazdıklarınızı hemen görmeniz gerekiyorsa işlemleri causally consistent (nedensel tutarlı) bir oturumda çalıştırın. Belgeler, nedensel tutarlılığın ancak okumalarda "majority" read concern ve yazmalarda "majority" write concern kullanıldığında garanti edildiğini belirtir.
Read Concern Seviyeleri

Read concern bir okumanın döndürdüğü verinin ne kadar kalıcı olduğunu belirler. Beş seviye vardır:
| Seviye | Döndürdüğü veri | Not |
|---|---|---|
| local | Örnekteki en güncel veri, çoğunluğa yazıldığı garanti değil | Primary ve secondary okumalarında varsayılan |
| available | local gibi, geri alınabilir veri | Nedensel oturum ve transaction içinde kullanılamaz |
| majority | Çoğunluk tarafından onaylanmış veri | Arıza olsa bile geri alınmaz |
| linearizable | Okuma başlamadan önce tamamlanan tüm çoğunluk yazmalarını yansıtır | Yalnızca primary üzerinde |
| snapshot | Belirli bir anın çoğunluk onaylı görüntüsü | Transaction ve bazı okuma komutlarında |
"available" sharded kümelerde en düşük gecikmeyi verir ama belgelerin uyardığı gibi sharded bir koleksiyondan sahipsiz (orphaned) belgeler döndürebilir; bu riski istemiyorsanız "local" kullanın. "majority", üyenin bellekteki çoğunluk onay noktasındaki görüntüsünden okur ve belgelere göre diğer seviyelerle karşılaştırılabilir bir performansa sahiptir; replica set'in WiredTiger kullanması gerekir. "linearizable" eşzamanlı yazmaların çoğunluğa yayılmasını bekleyebileceği için, üyelerin çoğunluğu erişilemez durumdayken süresiz beklememesi adına her zaman maxTimeMS ile birlikte kullanılmalıdır.
mongosh içinde bir find() sorgusu için seviyeyi imleç (cursor) yöntemiyle verirsiniz. Destekleyen komutlarda ise readConcern: { level: ... } seçeneği kullanılır:
db.siparisler.find({ musteri: "ayse" }).readConcern("majority")
db.siparisler.aggregate(
[ { $match: { tutar: { $gte: 100 } } } ],
{ readConcern: { level: "majority" } }
)Read Preference Modları
Read preference, istemcinin okuma işlemini hangi üyeye göndereceğini seçer. Varsayılan mod primary'dir. primary dışındaki tüm modlar, replikasyon eşzamansız olduğu için eski (stale) veri döndürebilir; uygulamanızın buna dayanabildiğinden emin olun.
| Mod | Davranış |
|---|---|
| primary | Yalnızca primary. Primary yoksa okuma hata verir. |
| primaryPreferred | Primary varsa ondan, yoksa uygun secondary üyelerden okur. |
| secondary | Yalnızca secondary üyelerden okur. Uygun secondary yoksa hata verir. |
| secondaryPreferred | Uygun secondary varsa ondan, yoksa primary üyeden okur. |
| nearest | Ağ gecikmesi kabul edilebilir pencere içindeki herhangi bir üyeden okur. |
Read preference'a etiket kümeleri (tag set) ve maxStalenessSeconds eklenebilir. maxStalenessSeconds bir secondary'nin ne kadar geride kalmışsa artık okuma için seçilmeyeceğini belirtir; en az 90 saniye olmalıdır, daha küçük bir değer hata üretir. Bu iki ayar primary moduyla birlikte kullanılamaz. mongosh içinde imleç üzerinde readPref() çağrılır:
db.raporlar.find({ yil: 2026 }).readPref("secondary")
db.raporlar.find({}).readPref("secondary", [ { bolge: "ist" }, { } ])İkinci örnekte önce bolge: "ist" etiketli secondary'ler aranır; bulunamazsa boş belge tüm uygun üyelerle eşleşir. Read preference verinin görünürlüğünü değiştirmez: primary'den okurken bile çoğunluğa henüz yayılmamış yazmaları görebilirsiniz. Bunu engelleyen ayar read preference değil read concern'dir.
Bağlantı Dizesinde ve Küme Genelinde Ayarlamak
Bu ayarları her işlemde tek tek vermek yerine bağlantı dizesinde verebilirsiniz. Belgelerdeki seçenek adları w, wtimeoutMS, journal, readConcernLevel, readPreference, maxStalenessSeconds ve readPreferenceTags şeklindedir. Bağlantı dizesi yapısı için connection string URI rehberine bakın.
mongodb://db1.ornek.lan,db2.ornek.lan,db3.ornek.lan/?replicaSet=rs0&w=majority&wtimeoutMS=5000&readConcernLevel=majorityKüme genelindeki varsayılanı değiştirmek için setDefaultRWConcern yönetim komutu kullanılır. Komut admin veritabanında; replica set'te primary üzerinde, sharded kümede bir mongos üzerinde çalıştırılır. Varsayılan write concern ayarlarken w alanını mutlaka belirtmelisiniz. Geçerli değerleri görmek için getDefaultRWConcern komutunu kullanın; yanıtta defaultWriteConcern, defaultReadConcern ve bunların kaynağını gösteren alanlar bulunur.
db.adminCommand({
setDefaultRWConcern: 1,
defaultWriteConcern: { w: "majority", wtimeout: 5000 },
defaultReadConcern: { level: "majority" }
})
db.adminCommand({ getDefaultRWConcern: 1 })Hangi Kombinasyonu Seçmeli?

- Kendi yazdığını primary'den okumak: Belgeler
"majority"read concern ile{ w: "majority" }write concern'i önerir. Seçim sırasında eski primary'ye giden bir okumanın, yeni primary'nin kabul ettiği çoğunluk onaylı bir yazmayı içermeyebileceğini de not eder. - Raporlama gibi gecikmeye toleranslı okumalar:
secondaryPreferredveyasecondaryile birliktemaxStalenessSecondskullanmak primary üzerindeki yükü azaltır. - Kayıp kabul edilebilir yüksek hacimli loglar:
w: 1düşük gecikme sağlar ama failover'da geri alınabilir; finansal veya sipariş verisi için uygun değildir. - Çoğunluktan büyük sayısal w: Belgeler,
wdeğerini hesaplanan çoğunluktan büyük seçerseniz varsayılan ayarlardaj: trueeklemenizi önerir; aksi halde yazma çoğunlukta kalıcı olmadan onay alabilirsiniz.
local veritabanı write concern desteklemez; bu veritabanındaki koleksiyonlara yapılan işlemlerde verdiğiniz write concern sessizce yok sayılır.
MongoDB 9.0 Notu: Change Stream ve Read Preference
MongoDB 9.0 uyumluluk notlarına göre readPreference değeri primary veya secondary olan bir change stream, seçim sonrasında bağlı olduğu üye artık bu tercihe uymuyorsa getMore çağrısında yeniden başlatılabilir InterruptedDueToReplStateChange hatasını (kod 11602) döndürür. Önceki sürümlerde imleç aynı üyeden sonuç döndürmeye devam ediyordu. Uyumlu sürücüler ve mongos son resume token'dan otomatik devam eder; elle yazılmış getMore döngüleri ve mongosh ise resumeAfter ile devam etmelidir. Ayrıntılar için change streams ve MongoDB 9.0 yenilikleri yazılarına bakın.
Sık Yapılan Hatalar
- PSA kümesinde
"majority"kullanıpwtimeoutvermemek: secondary bakımdayken yazmalar süresiz bekler. wtimeouthatasını yazmanın başarısız olduğu şeklinde yorumlayıp işlemi tekrar etmek.- Transaction içindeki tek tek işlemlere write concern veya read concern vermek.
secondaryokumasından hemen önceki yazmanın sonucunu görmeyi beklemek.maxStalenessSecondsdeğerini 90 saniyeden küçük vermek.- Hangi üyenin primary olacağını oy sayısıyla ayarlamaya çalışmak; bunun için
prioritykullanılır.
Sık Sorulan Sorular
Standalone sunucuda write concern işe yarar mı?
Kısmen. Standalone bir sunucu yazmayı bellekte veya journal'da onaylar. Belgelerdeki tabloya göre w: 1 ile j belirtilmezse onay bellekteki yazmadan sonra gelir, j: true ile diskteki journal'dan sonra gelir. Çoğunluk ve secondary kavramları ise yalnızca replica set'te anlam taşır.
Varsayılan write concern neden bazen w: 1 oluyor?
Kümenizde arbiter varsa ve veri tutan üye sayısı oy çoğunluğundan büyük değilse örtük varsayılan { w: 1 } olur. Tipik PSA kümesi bu durumdadır. setDefaultRWConcern ile açık bir varsayılan belirleyebilirsiniz.
Read concern "majority" yavaş mıdır?
Belgeler, "majority" seviyesinin bellekteki çoğunluk onay noktasından okuduğunu ve performansının diğer read concern seviyeleriyle karşılaştırılabilir olduğunu belirtir. Sorguyu yavaşlatmaz, yalnızca istemciye dönen veriyi değiştirir: çoğunlukta kalıcı olmayan bir değişikliği göstermez, bu yüzden en son yazmayı henüz göstermeyebilir.
Secondary'den okumak primary'nin yükünü her zaman azaltır mı?
Okuma yükünü dağıtır ama veri eskiliği maliyetiyle gelir ve secondary'ler de aynı yazma yükünü oplog üzerinden uygular. Yalnızca eski veriye toleranslı okumaları secondary'lere yönlendirin.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: MongoDB öğrenme rehberi · Replica set kurulumu · Transaction kullanımı · Sharding ve shard key · Change streams · Connection string URI