[最終更新] 2019年4月16日
DynamoDBはトランザクションをサポートしている。とはいえ基本的に原子性を求められるようなユースケースでは使わないほうがよいと思うけれど、できると幅が広がるので、覚えておいて損はない。ということで、boto3での使い方のメモ書き。
やること
以下のようなテーブルを作る。
- テーブル名 transact-test
- パーティションキー user_id
- user_idがhoge、user_nameがfugaさんのアイテムを投入
このtransact-testテーブルに、以下のような処理を行う。
- user_id=hogeのuser_nameをafterに変更する
- user_id=add を追加する
- 両方の処理が成功して初めて処理が反映される
更新と追加、両方の処理ができて初めて一つの処理とみなす、というテスト。
サンプルコード
以下のようなソースコードを書く。
"""boto3のtransact_write_items()を試すテストコード"""
import boto3
client_dynamo = boto3.client('dynamodb', region_name='ap-northeast-1')
TABLE_NAME = 'transact-test'
def dict2dynamoformat(orig_dict):
"""辞書配列をDynamoDB用に変換する"""
ret_dict = {}
for k, v in orig_dict.items():
print(k,v)
ret_dict[k] = _to_dynamo_format(v)
return ret_dict
def _to_dynamo_format(v):
"""dict2dynamoformatの変換部分でSet系の型は未対応"""
if type(v) is str:
return {'S': v}
if type(v) is int:
return {'N': str(v)}
if type(v) is bool:
return {'BOOL': v}
if type(v) is list:
return {'L': [_to_dynamo_format(a) for a in v]}
if type(v) is dict:
return {'M': dict2dynamoformat(v)}
if __name__ == '__main__':
item = {
'user_id': 'add',
'user_name': 'add_test',
}
item4dynamo = dict2dynamoformat(item)
client_dynamo.transact_write_items(
TransactItems=[
{
'Put': {
'TableName': TABLE_NAME,
'Item': item4dynamo,
},
},
{
'Update': {
'TableName': TABLE_NAME,
'Key': {
'user_id': {'S': 'hoge'}
},
'UpdateExpression': 'SET user_name = :un',
'ExpressionAttributeValues': {
':un': {'S': 'after'}
}
}
}
]
)
client_dynamo.transact_write_items()が書き換えの処理内容。使い方は「DynamoDB — Boto 3 Docs 1.9.121 documentation」を見るのが一番。boto3でDynamoDB使う時は、だいたいresourceを使うと思うのだが、transact_write_itemsを使いたいのであれば、抽象レベルの低いclientを用いる。そのうち対応されるのかなぁ。
dict2dynamoformatは、書き込みアイテムの配列が、普通の辞書配列をそのまんま突っ込んではダメなので、DynamoDBに登録できるように変換するための関数。Setな型には対応していない。自分が使ってないから……。
実行すると、ちゃんと書き換えが行われる。

片方でも失敗すると、どちらの処理も反映されない。
transact_write_items()なんかないと怒られた時
ひょっとすると、transact_write_ites()なんかないよと怒られるかもしれない。これはboto3が古いです。更新しましょう。
……ローカルなら更新しましょうでよいのだけれど、Lambdaで使おうとしてこれが出ると、新しいboto3を別環境でzip化して入れるという謎の工程が入ることになってしまってテンション下がる。そのうち対応されるのでしょうか。。。
参考記事
ありがとうございましたm(_ _)m
- DynamoDBのトランザクションを試してみた #reinvent | DevelopersIO
- AWSのサービスをモックするライブラリmotoを拡張してDynamoDBのTransactWriteItemsを実装する | DevelopersIO
関連記事
aws の記事
- [2020年4月26日] DynamoDBで多対多のテーブル設計
- [2020年4月17日] S3に指定のバケットにファイル生成したらSQSに通知
- [2019年6月12日] とにかくCloudSearch + boto3で全文検索するために学習する
- [2019年4月21日] DynamoDBのテーブル設計をするとき、自分に問いかけていること
- [2019年4月16日] S3 + CloudFrontでS3にファイルをアップロードしたら自動でキャッシュをクリアする
- ---本記事---
- [2019年1月22日] AWSのAPI Gateway + LambdaによるWeb APIでクエリ文字列を用いるcloudformation用テンプレートファイルの記述(swagger形式)
- [2019年1月14日] AWS SQSについて学ぶ
- [2019年1月12日] AWS CLIでよく使っているコマンド
- [2018年11月17日] S3に有効期限のあるURLを作って画像ファイルをPUTする
- [2018年8月22日] クラウドの利用について思う
スポンサーリンク