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

  • TransactItemsPut, Update, Delete ve ConditionCheck eylemlerinden 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, message ve __type'tır. err.code yoktur; üzerinde dallanılacak dize err.name'dir ve err.$metadata httpStatusCode: 400 artı attempts: 1 taşır — SDK'nın iptali sizin adınıza sessizce yeniden denemediğini böyle anlarsınız.
  • CancellationReasons konumsal ve seyrektir. Yukarıdaki işlem için [{"Code":"ConditionalCheckFailed","Message":"The conditional request failed"},{"Code":"None"}] olarak gelir. None girdisinin hiç Message özelliği yoktur; dolayısıyla err.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 nedenine Code ve Message'ın önünde, ham DynamoDB JSON biçiminde bir Item ekler. Kaybeden öğenin öznitelikleri bedavaya geri gelir; alternatifi, yarışı zaten kaybettikten sonra bir takip GetItem'ıdır.
  • err.name denetiminin bir boşluğu var ve hangisi olduğunu bilmeye değer. İki eylemi aynı öğeye yöneltin; DynamoDB Transaction request cannot include multiple operations on one item mesajıyla ValidationException yanıtı verir ve hiç CancellationReasons göndermez, çünkü hiçbir şey denenmemiştir. Yukarıdaki else { 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 ClientRequestToken gönderir. Serileştirilmiş gövdeyi yakalamak hat üzerinde yepyeni bir UUID gösterir ve aynı komut nesnesinin iki send() ç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 yerine IdempotentParameterMismatch alı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 — ConditionalCheckFailed iç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

Kaynaklar

En son 2026-07-28 tarihinde yukarıda bağlantısı verilen resmi AWS belgelerine karşı doğrulandı.

Console olmadan DynamoDB ile çalış

DynamoDB’nin çalıştıramadığı gerçek SQL’i çalıştıran hızlı bir DynamoDB masaüstü istemcisi — JOINs, GROUP BY, toplamalar — görsel düzenleme ve kendi Bedrock anahtarların üzerinde bir yapay zekâ aracısıyla.

30 günlük ücretsiz deneme, kredi kartı yok — ardından süre sınırı olmayan Ücretsiz plan.