Node.js'te DynamoDB TransactWriteItems (AWS SDK v3)
Başarılı bir TransactWriteItemsCommand size neredeyse hiçbir şey söylemez: öğe yok, öznitelik yok, boş bir yanıt. İhtiyacınız olan her şey istisnanın üzerindedir; dolayısıyla SDK v3'te aşağıdaki catch bloğu asıl API yüzeyidir ve içine tam olarak neyin düştüğünü bilmeye değer. (Bir işlemin ne zaman doğru çağrı olduğu için bkz. DynamoDB işlemleri.)
Kod
import {DynamoDBClient, TransactWriteItemsCommand} from '@aws-sdk/client-dynamodb';
const client = new DynamoDBClient({region: 'us-east-1'});
// Move one award between two songs — atomically. If the first song has no
// award to give, NEITHER update happens.
const command = new TransactWriteItemsCommand({
TransactItems: [
{
Update: {
TableName: 'Music',
Key: {Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'Cubano Chant'}},
UpdateExpression: 'SET #upd0 = #upd0 - :one',
ConditionExpression: '#upd0 >= :one',
ExpressionAttributeNames: {'#upd0': 'Awards'},
ExpressionAttributeValues: {':one': {N: '1'}}
}
},
{
Update: {
TableName: 'Music',
Key: {Artist: {S: 'Arturo Sandoval'}, SongTitle: {S: 'A Mis Abuelos'}},
UpdateExpression: 'SET #upd0 = if_not_exists(#upd0, :zero) + :one',
ExpressionAttributeNames: {'#upd0': 'Awards'},
ExpressionAttributeValues: {':one': {N: '1'}, ':zero': {N: '0'}}
}
}
]
});
try {
await client.send(command);
console.log('Transaction committed');
} catch (err) {
if (err.name === 'TransactionCanceledException') {
// One reason per action, in TransactItems order. 'None' means that action
// was fine — some OTHER action sank the transaction.
const codes = (err.CancellationReasons ?? []).map((r) => r.Code);
console.log('Transaction canceled:', codes); // e.g. ['ConditionalCheckFailed', 'None']
} else {
throw err;
}
}Açıklama
TransactItems—Put,Update,DeleteveConditionCheckeylemlerinden oluşan sıralı bir dizi. Sıra, yürütme sırası değildir (işlem atomiktir), ama başarısızlık nedenlerinin geri geldiği sıra odur — ki onu önemsemenin tek nedeni de budur. Üst sınırlar aşağıda ele alınıyor.- v3'ün gerçekte ne fırlattığı. Yakalanan nesnenin kendi özellikleri
$fault,$retryable,$metadata,name,CancellationReasons,messageve__type'tır.err.codeyoktur; üzerinde dallanılacak dizeerr.name'dir veerr.$metadatahttpStatusCode: 400artıattempts: 1taşır — SDK'nın iptali sizin adınıza sessizce yeniden denemediğini böyle anlarsınız. CancellationReasonskonumsal ve seyrektir. Yukarıdaki işlem için[{"Code":"ConditionalCheckFailed","Message":"The conditional request failed"},{"Code":"None"}]olarak gelir.Nonegirdisinin hiçMessageözelliği yoktur; dolayısıylaerr.CancellationReasons.map((r) => r.Message.trim())tam da başarılı olan eylemlerde hata işleyicinizin içinde hata fırlatır.ReturnValuesOnConditionCheckFailure: 'ALL_OLD', o eylemin nedenineCodeveMessage'ın önünde, ham DynamoDB JSON biçiminde birItemekler. Kaybeden öğenin öznitelikleri bedavaya geri gelir; alternatifi, yarışı zaten kaybettikten sonra bir takipGetItem'ıdır.err.namedenetiminin bir boşluğu var ve hangisi olduğunu bilmeye değer. İki eylemi aynı öğeye yöneltin; DynamoDBTransaction request cannot include multiple operations on one itemmesajıylaValidationExceptionyanıtı verir ve hiçCancellationReasonsgöndermez, çünkü hiçbir şey denenmemiştir. Yukarıdakielse { throw err }dalı onu yeniden fırlatır. Bu bir hata değil, doğru davranıştır; ama yapısal hataların iptal günlüklemenize hiç ulaşmaması demektir.- v3 siz atlasanız bile zaten bir
ClientRequestTokengönderir. Serileştirilmiş gövdeyi yakalamak hat üzerinde yepyeni bir UUID gösterir ve aynı komut nesnesinin ikisend()çağrısı iki farklı belirteçle çıktı. Yani belirteç, sizin kendi yeniden deneme döngünüzü değil, uçuştaki tek bir çağrıyı korur: yakalayın, yeniden gönderin; yeni bir belirteciniz olur ve idempotentlik olmaz. Bir yeniden deneme süreç sınırını aşabiliyorsa kendinizinkini verin. Onu herhangi bir parametre değişmişken yeniden kullanırsanız, sessiz bir çift uygulama yerineIdempotentParameterMismatchalırsınız. - Yalnızca bir başka kodun kendi kod yoluna ihtiyacı vardır.
TransactionConflict, eşzamanlı bir işlemin öğelerinizden birini tuttuğu anlamına gelir; dolayısıyla geri çekilmeli bir yeniden deneme doğru yanıttır —ConditionalCheckFailediçin ise asla değildir. Geri kalanı TransactionCanceledException sayfasında çözülür. - Maliyet — bir işlemdeki her öğe alt katmanda iki kez yazılır (önce hazırlık, sonra commit); dolayısıyla düz bir yazmanın yazma kapasitesinin kabaca 2× katını bütçeleyin. Tek öğelik bir koşullu yazma size tek öğe üzerinde atomikliği bunun yarısına verir.
Önce hangi sınıra çarparsınız
100 eylemlik üst sınır ile 4 MB'lık üst sınır birbirinden bağımsızdır ve insanları şaşırtan bayt olanıdır: yüz sayaç artırımı hiçbir şey değilken, bir düzine şişman öğe toplamı tek başına tüketebilir. Kaç eylem gruplayacağınıza karar vermeden önce temsili bir öğeyi DynamoDB öğe boyutu hesaplayıcısıyla ölçün. Bir eylemin dokunacağı öğeleri daha koşulu yazarken okumak için DynoTable'ı indirin.
İlgili örnekler
- Python'da DynamoDB TransactWriteItems — boto3 ile aynı işlem.
- AWS CLI ile DynamoDB TransactWriteItems — kabuktan aynı işlem.
- Node.js'te DynamoDB koşullu yazma — 2× maliyet olmadan tek öğe atomikliği.
- DynamoDB işlemleri — yalıtım, idempotentlik ve işlemler ne zaman değer.
- DynamoDB TransactionCanceledException — her iptal-nedeni kodu, çözülmüş hâliyle.
- "Too many actions in a TransactWriteItems call" — 100 eylemlik ve 4 MB'lık işlem sınırları.
- "Transaction request cannot include multiple operations on one item" — işlem başına öğe başına bir eylem.
Kaynaklar
- TransactWriteItems — Amazon DynamoDB API Reference
- Amazon DynamoDB transactions: how it works — Amazon DynamoDB Developer Guide
- DynamoDB read and write operations (capacity unit consumption) — Amazon DynamoDB Developer Guide
En son 2026-07-28 tarihinde yukarıda bağlantısı verilen resmi AWS belgelerine karşı doğrulandı.