DynamoDB 和具有版本號碼的樂觀鎖定 - Amazon DynamoDB

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

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 參數的資訊,請參閱「D 的選用組態設定ynamoDBMapper 」。

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

注意

此 transactionWrite 方法不支援 D ynamoDBMapperConfig.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));