DynamoDB Localを利用していると極稀に同一のハッシュキーのレコードが2重に作成されテーブルへのアクセスが不能な状態に陥ってしまう時があります。
重複エラー状態になった時の対処法はテーブルの再作成またはDynamoDB Local内のDBを直接操作して該当レコードを削除するで対処できます。
テーブルの再作成
データが全部消えても問題ない場合はテーブルを一度削除して再作成するのが手っ取り早い解決法になるかと思います。
テーブルの削除
$ aws dynamodb delete-table --table-name TARGET_TABLE
テーブルの作成
$ aws dynamodb create-table --table-name TARGET_TABLE ...その他オプション省略
DynamoDB Local内のDBを直接操作する
DynamoDB LocalのバックエンドはただのSQLiteのため、shellログインして直接SQLiteのレコードを操作して修正します。
$ docker exec local-dynamodb /bin/bash
または
$ docker-compose exec local-dynamodb /bin/bash
shellログインしたhomeディレクトリにSQLiteのdbは存在します。
$ ls -l
-rw-r--r-- 1 dynamodblocal dynamodblocal 19919872 Jan 22 01:06 AKIAXXXXXXXXXXXXXXX1_ap-northeast-1.db
-rw-r--r-- 1 dynamodblocal dynamodblocal 2527232 Jan 22 01:06 AKIAXXXXXXXXXXXXXXX2_ap-northeast-1.db
-rw-r--r-- 1 root root 3787546 May 29 2020 DynamoDBLocal.jar
drwxr-xr-x 2 root root 4096 Aug 20 03:32 DynamoDBLocal_lib
-rw-r--r-- 1 root root 8644 May 29 2020 LICENSE.txt
-rw-r--r-- 1 root root 1856 May 29 2020 README.txt
...略
DynamoDB Localでテーブル作成時に設定したAWS AccessKeyとregionを繋げたdbが作成されているのでエラーが発生しているdbを選びsqliteコマンドで接続します。
今回は仮にAWS AccessKeyがAKIAXXXXXXXXXXXXXXX1でregionがap-northeast-1だとします。
$ sqlite AKIAXXXXXXXXXXXXXXX1_ap-northeast-1.db
tableのschema情報を見てみる
sqlite> .schema TARGET_TABLE
CREATE TABLE "TARGET_TABLE"(
hashKey TEXT,
ObjectJSON,
itemSize INT,
hashValue
);
CREATE INDEX "TARGET_TABLE*HVI" ON "TARGET_TABLE" (hashValue);
どのテーブルもhashKey, ObjectJSON, itemSize, hashValueの構成で出来ています。
実際に1件取得してみると以下のように格納されています(本当は | 区切りですが便宜上改行で区切りに編集しています)
sqlite> SELECT * FROM TARGET_TABLE LIMIT 1;
hash-key-value
{"value": {"N": 0},"updated_at":{"N":"1603954694880509"}}
74
jF
重複レコードを両方消したい場合は単純にhashKeyでselectしたレコードを削除します。
sqlite> DELETE FROM TARGET_TABLE WHERE hashKey = 'HASH-KEY'
重複レコードどちらでもいいのでとにかく1件だけ削除したい場合は以下のクエリーを実行します。
sqlite> DELETE FROM TARGET_TABLE WHERE hashKey IN (SELECT hashKey FROM TARGET_TABLE WHERE = 'HASH-KEY' LIMIT1)
何かしら差分が発生しており特定のレコードだけ削除したい場合はObjectJSONカラムに対してLIKE検索をして削除するといいかと思います。
sqlite> DELETE FROM TARGET_TABLE WHERE hashKey = 'HASH-KEY' AND ObjectJSON LIKE '%残って欲しくないレコードの値%';
以上、同様の問題で困っている方の参考になれば。