DynamoDB Transaction'ları
Bir DynamoDB transaction'ı, birkaç yazmayı tek bir ya-hep-ya-hiç işlemde gruplandırır: ya her eylem commit edilir ya da hiçbiri. İlişkili iki öğenin bir yazma yarı-başarısız olduğunda birbirinden ayrılmasını önlemenin yoludur.
Denetim günlüğü senaryosunda, eklediğiniz her olay aynı zamanda kiracı bazında bir
eventCount'u da artırmalıdır. Olay düşer ama sayaç düşmezse — ya da tersi — günlük
ve sayım sonsuza dek anlaşmazlığa düşer. Bir transaction bunu imkânsız kılar.
DynamoDB transaction'ları destekliyor mu?
Evet. DynamoDB, TransactWriteItems ve TransactGetItems aracılığıyla ACID transaction'larını destekler; bu API'ler bir veya daha fazla tabloda 100'e kadar eylemi tek bir ya-hep-ya-hiç işlemde gruplandırır. Ya her yazma commit edilir ya da hiçbiri, bu sayede ilişkili öğeler birbirinden ayrılamaz. Transactional yazmalar normal yazmaların iki katı kapasite tüketir; başarısız bir koşul veya çakışma ise tüm isteği iptal eder.
TransactWriteItemsbir veya daha fazla tabloda 100'e kadar yazma eylemini gruplandırır, ya-hep-ya-hiç. Toplam öğe boyutu 4 MB'yi aşamaz.- Eylemler
Put,Update,DeleteveConditionCheck'tir. BirConditionCheck, yazmadığınız bir öğe hakkında bir şey doğrular. - Maliyeti iki katıdır. Bir transactional yazma, normal bir yazmanın iki katı kapasite tüketir — DynamoDB hazırlar sonra commit eder.
- Çakışmalar ve başarısız koşullar tüm işlemi iptal eder — bir
TransactionCanceledExceptionile; geride hiçbir kısmi şey kalmaz.
Sorun: anlaşması gereken iki yazma
Her yeni denetim olayının kiracının çalışan sayımını da artırmasını istersiniz. İki ayrı çağrı olarak yapıldığında, aralarındaki herhangi bir başarısızlık verinizi bozar:
- Yeni
EVENT#…öğesiniPutItem— başarılı. ADD eventCount 1içinUpdateItem— zaman aşımına uğrar.
Şimdi günlüğün sayacın iddia ettiğinden bir satır fazlası var. 2. adımı körü körüne yeniden denemek çift-sayma riski taşır; yeniden denememek onları tutarsız bırakır. Güvenli bir kurtarma yok çünkü iki yazma hiç bağlanmamıştı.
SQL'den gelirken, ikisini de BEGIN … COMMIT içine sarardınız. DynamoDB'nin yanıtı,
her iki yazmayı birlikte taşıyan tek bir transactional istektir.
TransactWriteItems nasıl çalışır
AWS Geliştirici Kılavuzu'na
göre TransactWriteItems, 100'e kadar farklı öğeyi hedefleyen "100'e kadar yazma
eylemini tek bir ya-hep-ya-hiç işlemde gruplandırır" ve "transaction'daki öğelerin
toplam boyutu 4 MB'yi aşamaz." Eylemler atomik olarak tamamlanır — hepsi başarılı olur
ya da hiçbiri olmaz.
Bir transaction'da dört eylem türünü karıştırabilirsiniz:
Put— bir öğe oluştur ya da değiştir.Update— öznitelikleri düzenle (sayacımız içinADDdahil).Delete— bir öğeyi anahtarına göre kaldır.ConditionCheck— başka türlü yazmadığınız bir öğe üzerinde bir koşul doğrula (ör. "bu kiracı hâlâ aktif").
Pratikte ısıran iki kural daha var. İlk olarak, transaction'lar eşdeğer transactional-olmayan yazmaların iki katı kapasite tüketir — DynamoDB bir hazırlık aşaması ve bir commit aşaması yapar. İkinci olarak, bir transaction'da aynı öğeyi iki kez hedefleyemezsiniz ve transaction'lar index'lere karşı gerçekleştirilemez.
Çalışılmış bir örnek: ekleme + sayım, atomik olarak
Denetim günlüğüne dönelim. acme kiracısı için bir olay eklemek ve sayacını artırmak,
iki eylemli tek bir transaction'dır:
| eylem | öğe | etki | |
|---|---|---|---|
| Put | TENANT#acme | EVENT#2026-06-24T09:14Z#a1 | yeni denetim satırını yaz |
| Update | TENANT#acme | COUNTER | ADD eventCount 1 |
Eylemlerden birinin koşulu başarısız olursa — diyelim kiracının askıya alınmadığını
doğrulayan bir ConditionCheck — tüm istek bir TransactionCanceledException ile
iptal edilir ve hiçbir yazma gerçekleşmez. Günlük ve sayaç asla anlaşmazlığa
düşemez.
Her eylemdeki ConditionExpression kaldıraçtır. Olay satırının zaten var olmadığını
(böylece bir yeniden deneme onu çoğaltamaz) ve kiracının aktif olduğunu doğrulamak
için, Put üzerinde attribute_not_exists(SK) ve bir ConditionCheck olarak
status = :active gibi koşullar oluşturursunuz.
Bu türlenmiş koşul ifadelerini ExpressionAttributeNames ve :val yer tutucularını
elle birleştirmek yerine
DynamoDB Expression Builder'da oluşturun ve
kopyalayın — koşullu-yazma modu tam olarak TransactWriteItems'ın istediği şekli
yayımlar.
Kararsız bir bağlantıda güvenli yeniden denemeler için bir client token ekleyin:
10 dakika içinde aynı token'la tekrarlanan bir TransactWriteItems, yazmaları yeniden
uygulamadan başarı döndürür
(idempotency).
DynoTable'da yapın
DynoTable kendi yazmaları için transaction'ları arka planda kullanır: birkaç öğe
düzenlemesini hazırlayıp commit ettiğinizde, bunları optimistik-kilitleme koşul
ifadeleriyle TransactWriteItems olarak gönderir, böylece düzenleme partiniz
ya-hep-ya-hiç olur — çok öğeli bir değişikliği asla yarı-uygulamazsınız.
Bu, olay satırını ve sayacı aynı hazırlanmış partide düzenleyebileceğiniz, diff'i gözden geçirebileceğiniz ve hiç SDK kodu yazmadan ikisini de atomik olarak commit edebileceğiniz anlamına gelir.

Tuzaklar ve sonraki adımlar
- İki kat kapasite bütçeleyin. Bir transactional yazma, düz bir yazmanın iki katı WCU faturalandırır — ara sıra tutarlılık-kritik bir çift için sorun değil, her tek yazmayı bir transaction'a sararsanız maliyetli. Atomikliğin gerçekten önemli olduğu yerde kullanın.
TransactionCanceledException'ı açıkça yönetin. Başarısız bir koşul ya da aynı öğeler üzerinde başka bir uçuştaki transaction ile bir çakışma için döndürülür. İptal nedenleri hangi eylemin başarısız olduğunu söyler — onları inceleyin, körü körüne yeniden denemeyin.- Stream kayıtları transaction-farkında değildir. Bir transaction'dan gelen değişiklikler Streams'e kademeli olarak yayılır ve diğerleriyle iç içe geçebilir; tüketiciler atomiklik ya da sıralama varsayamaz — bkz. DynamoDB Streams.
- Yüksek-throughput sayaçlar için değil. Ağır eşzamanlı transactional yük altında tek bir sıcak sayaç throttle olur; bunun için atomik sayaçlar'a bakın ya da sayacı parçalayın.
Transaction'lar "bu yazmalar anlaşmalı" için araçtır. Olaylar tutarlı bir şekilde düşmeye başladığında, sonraki endişe onlara tepki vermektir — bu DynamoDB Streams.
Çok öğeli düzenlemeleri hazırlayıp kendi tablonuza karşı tek bir transaction olarak commit etmek için DynoTable'ı indirin.


