DynamoDBのTransactionを使った取得処理

DynamoDBのトランザクションを使った取得処理を見ていきます。

使うテーブルは新しく用意しました。
・テーブル名「XpTable」
・キー名「XpKey」

DynamoDBのトランザクションを使った取得処理

 

実行環境
・Lambda(node.js)
AWS SDKはnpmで最新をダウンロードしてください。
Lambda内にデフォルトで入っている物は古いので下記を参考にAWS SDKを用意してください。

DynamoDBでTransactionの使い方(正常系)

 

ひとまず簡単に取得してみる

XpTableに適当なデータを作成します。

データを作成

Lambdaを作成し次のコードを実行し、取得してみます。

console.log('Loading function');
var AWS = require('aws-sdk');
var dynamoDb = new AWS.DynamoDB();

exports.handler = async (event, context) => {
  var data = await dynamoDb.transactGetItems({
    TransactItems: [
      {
        "Get": {
          "TableName": "XpTable",
          "Key": {
            "XpKey" : {"S": "XpKey1"}
          }
        }
      }
    ]
  }).promise();
  return data;
};

データが取得できました。

データ取得

 

検証

それでは、きちんと一貫性が保たれているか検証してみしょう。

次のような処理を実行してみます。

console.log('Loading function');
var AWS = require('aws-sdk');
var dynamoDb = new AWS.DynamoDB();

exports.handler = async (event, context) => {
  for (var value = 1 ; value < 100 ; value++) {
    var data = await dynamoDb.transactWriteItems({
      TransactItems: [
        {
          Update: {
            TableName: 'XpTable',
            Key: { XpKey: { S: 'XpKey1' } },
            UpdateExpression: 'set XpValue = :value',
            ExpressionAttributeValues: {
              ':value': { S: value + '' }
            }
          }
        },
        {
          Update: {
            TableName: 'XpTable',
            Key: { XpKey: { S: 'XpKey2' } },
            UpdateExpression: 'set XpValue = :value',
            ExpressionAttributeValues: {
              ':value': { S: value + '' }
            }
          }
        },
        {
          Update: {
            TableName: 'XpTable',
            Key: { XpKey: { S: 'XpKey3' } },
            UpdateExpression: 'set XpValue = :value',
            ExpressionAttributeValues: {
              ':value': { S: value + '' }
            }
          }
        }
      ]
    }).promise();
  }
  return data;
};

 

内容はXpTableのXpKey1、XpKey2、XpKey3のデータを「1」に更新。
XpKey1、XpKey2、XpKey3のデータを「2」に更新。
という具合に3つのアイテムをトランザクションを使いながら同時に更新していきます。

タイムアウトすると困るのでタイムアウトを30秒にしておきます。

 

トランザクションを使いながら同時に更新

実行完了までに何秒かかかるので、その間に次のコードを実行してみます。

console.log('Loading function');
var AWS = require('aws-sdk');
var dynamoDb = new AWS.DynamoDB();

exports.handler = async (event, context) => {
  var data1 = await dynamoDb.getItem({
    "TableName": "XpTable",
    "Key": {
      "XpKey" : {"S": "XpKey1"}
    }
  }).promise();
  var data2 = await dynamoDb.getItem({
    "TableName": "XpTable",
    "Key": {
      "XpKey" : {"S": "XpKey2"}
    }
  }).promise();
  var data3 = await dynamoDb.getItem({
    "TableName": "XpTable",
    "Key": {
      "XpKey" : {"S": "XpKey3"}
    }
  }).promise();
  var dataTran = await dynamoDb.transactGetItems({
    TransactItems: [
      {
        "Get": {
          "TableName": "XpTable",
          "Key": {
            "XpKey" : {"S": "XpKey1"}
          }
        }
      },
      {
        "Get": {
          "TableName": "XpTable",
          "Key": {
            "XpKey" : {"S": "XpKey2"}
          }
        }
      },
      {
        "Get": {
          "TableName": "XpTable",
          "Key": {
            "XpKey" : {"S": "XpKey3"}
          }
        }
      }
    ]
  }).promise();
  return {
    data1:data1,
    data2:data2,
    data3:data3,
    dataTran:dataTran
  };
};

 

次のような結果になりました。

 

実行結果

 

以下全文

{
  "data1": {
    "Item": {
      "XpValue": {
        "S": "8"
      },
      "XpKey": {
        "S": "XpKey1"
      }
    }
  },
  "data2": {
    "Item": {
      "XpValue": {
        "S": "8"
      },
      "XpKey": {
        "S": "XpKey2"
      }
    }
  },
  "data3": {
    "Item": {
      "XpValue": {
        "S": "9"
      },
      "XpKey": {
        "S": "XpKey3"
      }
    }
  },
  "dataTran": {
    "Responses": [
      {
        "Item": {
          "XpValue": {
            "S": "10"
          },
          "XpKey": {
            "S": "XpKey1"
          }
        }
      },
      {
        "Item": {
          "XpValue": {
            "S": "10"
          },
          "XpKey": {
            "S": "XpKey2"
          }
        }
      },
      {
        "Item": {
          "XpValue": {
            "S": "10"
          },
          "XpKey": {
            "S": "XpKey3"
          }
        }
      }
    ]
  }
}

実行タイミングによっては値が違うかもしれませんが、トランザクションが無い方は値がバラバラになっており、トランザクションがある方は値が一緒になっています。

 

最後に

transactGetItemsを使うと一貫性が保持されているのが検証できました。
リレーションがある場合、トランザクションを使った方が正確な値が取得しやすいため
どんどん使っていってください。

 

 

AWS相談会