含版本編號的樂觀鎖定 - Amazon DynamoDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

含版本編號的樂觀鎖定

樂觀鎖定是一種策略,確保您要更新 (或刪除) 的用戶端項目與 Amazon DynamoDB 中的項目相同。如果您使用此策略,則會保護其他項目的寫入不會覆寫資料庫寫入,反之亦然。

使用樂觀鎖定,每個項目都有做為版本編號的屬性。如果您從資料表中擷取項目,則應用程式會記錄該項目的版本編號。您可以更新項目,但只有在伺服器端的版本編號尚未變更時。若版本不相符,表示已有其他人在您之前進行修改。更新嘗試失敗,因為您有此項目的過期版本。如果發生這種情況,請擷取項目,然後嘗試更新項目,再試一次。樂觀鎖定預防您意外覆寫其他人所作的變更。同時也預防其他人意外覆寫您所作的變更。

雖然您可以實現自己的樂觀鎖定策略,但 AWS SDK for Java 提供了@DynamoDBVersionAttribute註釋。在資料表的映射類別中,您指定一個屬性來存放版本編號,並使用此註釋進行標示。當您儲存物件時,DynamoDB 資料表中的對應項目會有屬性可存放版本編號。當您第一次儲存物件時,DynamoDBMapper 會指派版本編號,並在每次更新項目時自動遞增版本編號。只有在用戶端物件版本與 DynamoDB 資料表中項目的對應版本編號相符時,您的更新或刪除請求才會成功。

如果發生下列情況,則會擲回 ConditionalCheckFailedException

  • 您使用含 @DynamoDBVersionAttribute 的樂觀鎖定,而且伺服器上的版本值與用戶端上的值不同。

  • 您可以搭配使用 DynamoDBMapperDynamoDBSaveExpression,以在儲存資料時指定自己的條件式限制條件,而且這些限制條件會失敗。

注意
  • DynamoDB 全域資料表會在並行更新間使用「最後寫入者獲勝」核對機制。如果您使用的是全域資料表,最後寫入者政策獲勝。因此,在此情況下,鎖定政策不會如預期般運作。

  • DynamoDBMapper 交易寫入操作不支援同一物件的 @DynamoDBVersionAttribute 標註和條件表達式。如果一個事務性寫入中的對象被註釋,@DynamoDBVersionAttribute並且還具有一個條件表達式,那麼一個 SdkClientException 將被拋出。

例如,下列 Java 程式碼定義有數個屬性的 CatalogItem 類別。Version 屬性會標上 @DynamoDBVersionAttribute 註釋。

範例
@DynamoDBTable(tableName="ProductCatalog") public class CatalogItem { private Integer id; private String title; private String ISBN; private Set<String> bookAuthors; private String someProp; private Long version; @DynamoDBHashKey(attributeName="Id") public Integer getId() { return id; } public void setId(Integer Id) { this.id = Id; } @DynamoDBAttribute(attributeName="Title") public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @DynamoDBAttribute(attributeName="ISBN") public String getISBN() { return ISBN; } public void setISBN(String ISBN) { this.ISBN = ISBN;} @DynamoDBAttribute(attributeName = "Authors") public Set<String> getBookAuthors() { return bookAuthors; } public void setBookAuthors(Set<String> bookAuthors) { this.bookAuthors = bookAuthors; } @DynamoDBIgnore public String getSomeProp() { return someProp;} public void setSomeProp(String someProp) {this.someProp = someProp;} @DynamoDBVersionAttribute public Long getVersion() { return version; } public void setVersion(Long version) { this.version = version;} }

您可以將 @DynamoDBVersionAttribute 註釋套用至基本包裝函式類別所提供的可為 Null 類型,而基本包裝函式類別提供可為 Null 類型 (例如 LongInteger)。

樂觀鎖定對這些 DynamoDBMapper 方法的影響如下:

  • save:針對新項目,DynamoDBMapper 會指派初始版本編號 1。如果您擷取項目,請更新其一或多個屬性並嘗試儲存變更,只有在用戶端的版本編號與伺服器端的相符時,儲存操作才會成功。DynamoDBMapper 會自動遞增版本編號。

  • deletedelete 方法會採用物件作為參數,而 DynamoDBMapper 會在刪除項目之前執行版本檢查。如果請求中指定 DynamoDBMapperConfig.SaveBehavior.CLOBBER,則可以停用版本檢查。

    DynamoDBMapper 內的樂觀鎖定內部實作,使用 DynamoDB 所提供的條件式更新和條件式刪除支援。

  • transactionWrite

    • Put:針對新項目,DynamoDBMapper 會指派初始版本編號 1。如果您擷取項目,請更新其一或多個屬性並嘗試儲存變更,只有在用戶端的版本編號與伺服器端的相符時,Put 操作才會成功。DynamoDBMapper 會自動遞增版本編號。

    • Update:針對新項目,DynamoDBMapper 會指派初始版本編號 1。如果您擷取項目,請更新其一或多個屬性並嘗試儲存變更,只有在用戶端的版本編號與伺服器端的相符時,update 操作才會成功。DynamoDBMapper 會自動遞增版本編號。

    • DeleteDynamoDBMapper 會在刪除項目之前執行版本檢查。只有用戶端與伺服器端的版本號碼相符時,delete 操作才會成功。

    • ConditionCheck:不支援 ConditionCheck 操作的 @DynamoDBVersionAttribute 註釋。當一個ConditionCheck項目被註釋與 SdkClientException @DynamoDBVersionAttribute將被拋出。

停用樂觀鎖定

若要停用樂觀鎖定,您可以將 DynamoDBMapperConfig.SaveBehavior 列舉值從 UPDATE 變更為 CLOBBER。您可以建立跳過版本檢查的 DynamoDBMapperConfig 執行個體來執行這項操作,並將此執行個體用於所有請求。如需 DynamoDBMapperConfig.SaveBehavior 和其他選用 DynamoDBMapper 參數的資訊,請參閱「DynamoDBMapper 的選用組態設定 」。

您也只能設定特定操作的鎖定行為。例如,下列 Java 程式碼片段使用 DynamoDBMapper 來儲存型錄項目。指定 DynamoDBMapperConfig.SaveBehavior 的方式是將選用 DynamoDBMapperConfig 參數新增至 save 方法。

注意

transactionWrite 方法不支援 DynamoDB 援。MapperConfig SaveBehavior配置。不支援停用 transactionWrite 的樂觀鎖定。

範例
DynamoDBMapper mapper = new DynamoDBMapper(client); // Load a catalog item. CatalogItem item = mapper.load(CatalogItem.class, 101); item.setTitle("This is a new title for the item"); ... // Save the item. mapper.save(item, new DynamoDBMapperConfig( DynamoDBMapperConfig.SaveBehavior.CLOBBER));