NoSQL に関連するトランザクションが必要なため、DynamoDB を対象とした独自のソリューションを考え出すことにしました。欠陥、または改善のための提案を見つけた場合はお知らせください。
前提。トランザクションとして 2 つのオブジェクトを挿入します。
意味;
- 両方のオブジェクトが正常に挿入されない場合、挿入はロールバックします。
- トランザクションの進行中は、オブジェクトを読み取ることができません。
- 停電などの壊滅的な障害が発生した場合、ガベージ コレクターは孤立したオブジェクトを消去します。(トランザクションが失敗した場合、オブジェクトは孤立していると見なされます。)
機能の概要: 2 つのオブジェクトはそれぞれ、関連付けられた固有のトランザクション ID を共有します。両方の挿入が成功すると、トランザクション オブジェクトが成功ステータスでデータベースにコミットされます。失敗すると、両方のオブジェクトが削除されます。
//NOTE: insert means insert into the database
// delete means delete from the database
public void InsertTwoObjects()
{
String[] transaction_object = {'random Id', '0'};
String[] a = {'object 1', transaction[0]};
String[] b = {'object 2', transaction[0]};
try{
if !(insert(a) && insert(b))
{
throw new FailedInsertException();
}
else
{
transaction_object[1]='1';
if !(insert(transaction_object))
{
throw new FailedInsertException();
}
}
}
catch(FailedInsertExpcetion e)
{
//rollback
delete a;
delete b;
delete transaction_object;
}
}
ここで、従来のクエリ関数を置き換え、上記のトランザクション ロジックとの一貫性を維持する新しい queryDB 関数を定義する必要があります。別のプロセスでオブジェクトをクエリしようとすると、トランザクション オブジェクトが成功を示す値 1 を返さない限り失敗します。
public string QueryObject(String[] a)
{
String[] result = query(a);
if (result[1]==null)
{
return result[0];
}
String[] transaction = query(result[1]);
if (transaction[1]!='1')
{
throw new ItemNotFoundException();
}
else
{
return result[0];
}
}
最後のステップは、定期的なバッチ プロセスを用意することです。これは、ガベージ コレクターと同様に、データベースをスキャンして特定の経過時間よりも古い孤立したブロックを探し、それらを削除します。これは、最初の関数がロールバックを実行できない電力不足のためにトランザクションが失敗した場合に必要です。
public void BatchGargageCollect()
{
while(1==1)
{
wait(5000);
1. scan all objects with a transaction id appended to them
2. query the transaction.
3. If valid, remove the appended transaction id from the object.
}
}