1
0

More than 3 years have passed since last update.

DynamoDB Localで同一のハッシュキーが出来てしまった場合の対処法

Posted at

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 '%残って欲しくないレコードの値%';

以上、同様の問題で困っている方の参考になれば。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0