只有滿足條件時,才能對資料表中的資料進行更新;當不滿足條件時,更新失敗。

情境

適用於對高並發的應用進行更新的情境。

在高並發情境下,old_value可能被其他用戶端更新,如果使用條件更新,則只有在value等於old_value時,才更新value為new_value。
说明 在網頁計數和遊戲等高並發情境下,使用條件更新後,更新資料可能會失敗,此時需要一定次數的重試。
 //擷取當前值。
 old_value = Read();
 //對當前值進行運算,例如加1操作。
 new_value = func(old_value);
 //使用最新值進行更新。
 Update(new_value);
                

介面

條件更新支援關係運算(=、!=、>、>=、<、<=)和邏輯運算(NOT、AND、OR),支援最多10個條件的組合。適用於PutRowUpdateRowDeleteRowBatchWriteRow介面。

條件更新可以實現樂觀鎖功能,即在更新某行時,先擷取某列的值,假設為列A,值為1,然後設定條件列A=1,更新行使列A=2。如果更新失敗,表示有其他用戶端已成功更新該行。

列判斷條件包括列條件和行存在性條件。
列判斷條件 說明
列條件 目前支援SingleColumnValueCondition和CompositeColumnValueCondition,是基於某一列或者某些列的列值進行條件判斷,與過濾器Filter中的條件類似。
行存在性條件 對資料表變更操作時,系統會先檢查行存在性條件,如果不滿足行存在性條件,則更改失敗並給使用者報錯。
行存在性條件包括如下類型。
  • IGNORE:忽略
  • EXPECT_EXIST:期望存在
  • EXPECT_NOT_EXIST:期望不存在

通過不同介面操作資料表的資料時的行存在性條件更新規則的更多資訊,請參見行存在性條件更新規則

行存在性條件更新規則
说明 BatchWriteRow操作由多個PutRow、UpdateRow、DeleteRow子操作組成,所以通過BatchWriteRow介面操作資料表中的資料時,請根據操作類型查看對應介面的更新規則。
介面 IGNORE EXPECT_EXIST EXPECT_NOT_EXIST
PutRow(已存在行) 成功 成功 失敗
PutRow(不存在行) 成功 失敗 成功
UpdateRow(已存在行) 成功 成功 失敗
UpdateRow(不存在行) 成功 失敗 成功
DeleteRow(已存在行) 成功 成功 失敗
DeleteRow(不存在行) 成功 失敗 成功

使用

您可以使用如下語言的SDK實現條件更新功能。

樣本

使用列判斷條件和樂觀鎖的範例程式碼如下:

  • 構造SingleColumnValueCondition。
     //設定條件為Col0==0。
     SingleColumnValueCondition singleColumnValueCondition = new SingleColumnValueCondition("Col0",
             SingleColumnValueCondition.CompareOperator.EQUAL, ColumnValue.fromLong(0));
     //如果不存在Col0列,條件檢查不通過。
     singleColumnValueCondition.setPassIfMissing(false);
     //只判斷最新版本。
     singleColumnValueCondition.setLatestVersionsOnly(true);
                        
  • 構造CompositeColumnValueCondition。
     //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實現樂觀鎖機制,遞增一列。
     private static void updateRowWithCondition(SyncClient client, String pkValue) {
         //構造主鍵。
         PrimaryKeyBuilder primaryKeyBuilder = PrimaryKeyBuilder.createPrimaryKeyBuilder();
         primaryKeyBuilder.addPrimaryKeyColumn(PRIMARY_KEY_NAME, 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());
         }
     }
                        

計費

資料寫入或者更新成功,不影響各個介面的CU計算規則,如果條件更新失敗,則會消耗1單位寫CU和1單位讀CU。