シナリオ
条件付き更新機能は、多数のクライアントがデータテーブルを同時に更新するシナリオに適用できます。この機能は、データの正確性と整合性を保証します。
これらのシナリオでは、old_valueは他のクライアントによって更新される可能性があります。現在の値がold_valueと等しい場合にのみ、条件付き更新機能を使用して現在の値をnew_valueに更新できます。
重要 ページビュー(PV)カウントやゲームなどのシナリオでは、条件付き更新が失敗する可能性があります。このような場合、データ更新の再試行が必要です。
条件付き更新は、次の方法で実装されます。
現在の値を取得します。
現在の値が条件を満たしているかどうかを確認します。
機能の説明
PutRow、UpdateRow、DeleteRow、またはBatchWriteRow操作を呼び出してデータテーブルのデータを更新する場合、行存在条件と列ベースの条件を指定して条件付き更新を実行できます。データテーブルのデータは、条件が満たされた場合にのみ更新されます。
条件付き更新機能を使用して、オプティミスティックロックを実装できます。行を更新する場合、最初に列の値を取得できます。たとえば、列Aの値が1であるとします。次に、列Aの値が1であるという条件を設定し、条件付き更新を使用して値を2に更新できます。
更新が失敗した場合、行は他のクライアントによって更新されています。
条件付き更新に行存在条件と列ベースの条件を指定できます。
列ベースの条件
列ベースの条件には、SingleColumnValueConditionsとCompositeColumnValueConditionsが含まれ、1つ以上の列の値に基づいて条件ベースの判断を実行するために使用されます。列ベースの条件は、Tablestoreフィルターで使用される条件に似ています。
列ベースの条件は、=, !=, >, >=, <, <= NOT、AND、およびORなどの関係演算子と論理演算子をサポートしています。条件付き更新には、最大10個の列ベースの条件を指定できます。
行存在条件
データテーブルを更新する場合、Tablestoreは最初に、行存在条件が満たされているかどうかを確認します。行存在条件が満たされていない場合、更新は失敗し、エラーが報告されます。
IGNORE、EXPECT_EXIST、EXPECT_NOT_EXISTなどの行存在条件がサポートされています。
次の表は、異なる操作の行存在条件に基づく更新ルールを示しています。
説明 BatchWriteRow操作は、PutRow、UpdateRow、DeleteRowなどの複数のサブ操作で構成されます。BatchWriteRow操作を呼び出してデータテーブルのデータを更新する場合は、特定の操作の更新ルールを参照してください。
機能の使用
Tablestore CLIまたはTablestore SDKを使用して、条件付き更新機能を使用できます。
Tablestore CLIの使用
Tablestore CLIでデータを書き込んだり更新したりする場合に、条件付き更新機能を使用できます。
put
コマンドを実行してデータの行を挿入する場合に、行存在条件を指定します。詳細については、「データの操作」トピックの「データの行を挿入する」セクションを参照してください。
次のサンプルコマンドは、データテーブルに行を挿入します。行の最初のプライマリキー列の値は「86」です。2番目のプライマリキー列の値は6771です。行には、nameとcountryという2つの属性列が含まれています。name列とcountry列はSTRING型です。行が存在するかどうかに関係なく、データが挿入されます。行が存在する場合、挿入されたデータは既存のデータを上書きします。
put --pk '["86", 6771]' --attr '[{"c":"name", "v":"redchen"}, {"c":"country", "v":"china"}]' --condition ignore
update
コマンドを実行してデータの行を更新する場合に、行存在条件を指定します。詳細については、「データの操作」トピックの「データの行を更新する」セクションを参照してください。
次のサンプルコマンドは、最初のプライマリキー列の値が「86」で、2番目のプライマリキー列の値が6771であるデータの行を更新します。行が存在するかどうかに関係なく、データが更新されます。行が存在しない場合、データの行が挿入されます。
update --pk '["86", 6771]' --attr '[{"c":"name", "v":"redchen"}, {"c":"country", "v":"china"}]' --condition ignore
Tablestore SDKの使用
Tablestore SDK for Java、Tablestore SDK for Go、Tablestore SDK for Python、Tablestore SDK for Node.js、Tablestore SDK for .NET、Tablestore SDK for PHPを使用して、条件付き更新機能を使用できます。次の例では、Tablestore SDK for Javaを使用します。
列ベースの条件に基づいてデータを更新する
SinglleColumnValueConditionを構築する
次の例では、Col0列の値がCol0==0
の条件を満たす場合、Col0列の値が更新されます。
private static void updateRowWithSingleColumnValueCondition(SyncClient client, String pkValue){
// プライマリキーを構築します。
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
PrimaryKey primaryKey = primaryKeyBuilder.build();
// データの行を読み取ります。
SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("<TABLE_NAME>", primaryKey);
criteria.setMaxVersions(1);
GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
Row row = getRowResponse.getRow();
long col0Value = row.getLatestColumn("Col0").getValue().asLong();
// データテーブルの名前を指定します。
RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);
// 条件を設定します:Col0==0。
SingleColumnValueCondition singleColumnValueCondition = new SingleColumnValueCondition("Col0",
SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromLong(0));
// Col0列が存在しない場合、条件チェックは失敗します。
singleColumnValueCondition.setPassIfMissing(false);
// 最新バージョンのみを比較に使用するように指定します。
singleColumnValueCondition.setLatestVersionsOnly(true);
Condition condition = new Condition();
condition.setColumnCondition(singleColumnValueCondition);
rowUpdateChange.setCondition(condition);
// Col0列の値が列ベースの条件を満たす場合、Col0列の値が1ずつ増加します。
rowUpdateChange.put(new Column("Col0", ColumnValue.fromLong(col0Value+1)));
try {
client.updateRow(new UpdateRowRequest(rowUpdateChange));
System.out.println("データが更新されました。");
} catch (TableStoreException ex) {
System.out.println("データの更新に失敗しました。" + ex.toString());
}
}
CompositeColumnValueConditionを構築する
次の例では、Col0列の値がCol0==0 AND Col1>100
およびCol2<=10
のいずれかの条件を満たす場合、Col0列の値が更新されます。
private static void updateRowWithCompositeColumnValueCondition(SyncClient client, String pkValue){
// プライマリキーを構築します。
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
PrimaryKey primaryKey = primaryKeyBuilder.build();
// データの行を読み取ります。
SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("<TABLE_NAME>", primaryKey);
criteria.setMaxVersions(1);
GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
Row row = getRowResponse.getRow();
long col0Value = row.getLatestColumn("Col0").getValue().asLong();
// データテーブルの名前を指定します。
RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);
// composite1条件を(Col0 == 0) AND (Col1 > 100)に設定します。
CompositeColumnValueCondition composite1 = new CompositeColumnValueCondition(CompositeColumnValueCondition.LogicOperator.AND);
SingleColumnValueCondition single1 = new SingleColumnValueCondition("Col0",
SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromLong(0));
SingleColumnValueCondition single2 = new SingleColumnValueCondition("Col1",
SingleColumnValueCondition.CompareOperator.GREATER_THAN, ColumnValue.fromLong(100));
composite1.addCondition(single1);
composite1.addCondition(single2);
// composite2条件を((Col0 == 0) AND (Col1 > 100)) OR (Col2 <= 10)に設定します。
CompositeColumnValueCondition composite2 = new CompositeColumnValueCondition(CompositeColumnValueCondition.LogicOperator.OR);
SingleColumnValueCondition single3 = new SingleColumnValueCondition("Col2",
SingleColumnValueCondition.CompareOperator.LESS_EQUAL, ColumnValue.fromLong(10));
composite2.addCondition(composite1);
composite2.addCondition(single3);
Condition condition = new Condition();
condition.setColumnCondition(composite2);
rowUpdateChange.setCondition(condition);
// Col0列の値が列ベースの条件のいずれかを満たす場合、Col0列の値が1ずつ増加します。
rowUpdateChange.put(new Column("Col0", ColumnValue.fromLong(col0Value+1)));
try {
client.updateRow(new UpdateRowRequest(rowUpdateChange));
System.out.println("データが更新されました。");
} catch (TableStoreException ex) {
System.out.println("データの更新に失敗しました。" + ex.toString());
}
}
オプティミスティックロックに基づいてデータを更新する
次のサンプルコードは、オプティミスティックロックに基づいて列の値を増やす方法の例を示しています。
private static void updateRowWithCondition(SyncClient client, String pkValue) {
// プライマリキーを構築します。
PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
primaryKeyBuilder.addPrimaryKeyColumn("pk", PrimaryKeyValue.fromString(pkValue));
PrimaryKey primaryKey = primaryKeyBuilder.build();
// データの行を読み取ります。
SingleRowQueryCriteria criteria = new SingleRowQueryCriteria("<TABLE_NAME>", primaryKey);
criteria.setMaxVersions(1);
GetRowResponse getRowResponse = client.getRow(new GetRowRequest(criteria));
Row row = getRowResponse.getRow();
long col0Value = row.getLatestColumn("Col0").getValue().asLong();
// Col0列の値を1ずつ増やすように条件付き更新を構成します。
RowUpdateChange rowUpdateChange = new RowUpdateChange("<TABLE_NAME>", primaryKey);
Condition condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
ColumnCondition columnCondition = new SingleColumnValueCondition("Col0", SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromLong(col0Value));
condition.setColumnCondition(columnCondition);
rowUpdateChange.setCondition(condition);
rowUpdateChange.put(new Column("Col0", ColumnValue.fromLong(col0Value + 1)));
try {
client.updateRow(new UpdateRowRequest(rowUpdateChange));
} catch (TableStoreException ex) {
System.out.println(ex.toString());
}
}
課金
Tablestoreは、予約モードと従量課金モードの2つの課金モードをサポートしています。キャパシティユニット(CU)の課金は、課金モードによって異なります。
消費されるCUは、条件付き更新によってデータが正常に書き込まれたまたは更新された場合に実行される特定の操作に基づいて計算されます。条件付き更新が失敗した場合、1つの書き込みCUと1つの読み取りCUが消費されます。インスタンスタイプに基づいて、従量制読み取り/書き込みCUまたは予約読み取り/書き込みCUを使用できます。