本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
DynamoDB 和具有版本號碼的樂觀鎖定
樂觀鎖定是一種策略,確保您要更新 (或刪除) 的用戶端項目與 Amazon DynamoDB 中的項目相同。如果您使用此策略,則會保護其他項目的寫入不會覆寫資料庫寫入,反之亦然。
使用樂觀鎖定,每個項目都有做為版本編號的屬性。如果您從資料表中擷取項目,則應用程式會記錄該項目的版本編號。您可以更新項目,但只有在伺服器端的版本編號尚未變更時。若版本不相符,表示已有其他人在您之前進行修改。更新嘗試失敗,因為您有此項目的過期版本。如果發生這種情況,請擷取項目並嘗試更新,然後再試一次。樂觀鎖定預防您意外覆寫其他人所作的變更。同時也預防其他人意外覆寫您所作的變更。
雖然您可以實作自己的樂觀鎖定策略, AWS SDK for Java 會提供@DynamoDBVersionAttribute
註釋。在資料表的映射類別中,您指定一個屬性來存放版本編號,並使用此註釋進行標示。當您儲存物件時,DynamoDB 資料表中的對應項目會有屬性可存放版本編號。當您第一次儲存物件時,DynamoDBMapper
會指派版本編號,並在每次更新項目時自動遞增版本編號。只有在用戶端物件版本與 DynamoDB 資料表中項目的對應版本編號相符時,您的更新或刪除請求才會成功。
如果發生下列情況,則會擲回 ConditionalCheckFailedException
:
-
您使用含
@DynamoDBVersionAttribute
的樂觀鎖定,而且伺服器上的版本值與用戶端上的值不同。 -
您可以搭配使用
DynamoDBMapper
與DynamoDBSaveExpression
,以在儲存資料時指定自己的條件式限制條件,而且這些限制條件會失敗。
注意
-
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 類型 (例如 Long
和 Integer
)。
樂觀鎖定對這些 DynamoDBMapper
方法的影響如下:
-
save
:針對新項目,DynamoDBMapper
會指派初始版本編號 1。如果您擷取項目,請更新其一或多個屬性並嘗試儲存變更,只有在用戶端的版本編號與伺服器端的相符時,儲存操作才會成功。DynamoDBMapper
會自動遞增版本編號。 -
delete
:delete
方法會採用物件作為參數,而DynamoDBMapper
會在刪除項目之前執行版本檢查。如果請求中指定DynamoDBMapperConfig.SaveBehavior.CLOBBER
,則可以停用版本檢查。DynamoDBMapper
內的樂觀鎖定內部實作,使用 DynamoDB 所提供的條件式更新和條件式刪除支援。 -
transactionWrite
—-
Put
:針對新項目,DynamoDBMapper
會指派初始版本編號 1。如果您擷取項目,請更新其一或多個屬性並嘗試儲存變更,只有在用戶端的版本編號與伺服器端的相符時,Put 操作才會成功。DynamoDBMapper
會自動遞增版本編號。 -
Update
:針對新項目,DynamoDBMapper
會指派初始版本編號 1。如果您擷取項目,請更新其一或多個屬性並嘗試儲存變更,只有在用戶端的版本編號與伺服器端的相符時,update 操作才會成功。DynamoDBMapper
會自動遞增版本編號。 -
Delete
:DynamoDBMapper
會在刪除項目之前執行版本檢查。只有用戶端與伺服器端的版本號碼相符時,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));