本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 DynamoDB 交易進行估算鎖定
DynamoDB 交易提供all-or-nothing方法。當您使用 時TransactWriteItems,DynamoDB 會監控交易中的所有項目。如果在交易期間由其他操作修改任何項目,則整個交易都會取消,且 DynamoDB 會傳回 TransactionCanceledException。這種行為提供一種可觀的並行控制形式,因為防止衝突並行修改,而不是在事實之後偵測到。
何時使用交易進行鎖定
在下列情況下,交易非常適合:
您需要以原子方式更新多個項目,無論是在同一資料表內或跨資料表。
您的商業邏輯需要all-or-nothing語意 - 所有變更都成功套用或不套用。
常見範例包括在帳戶之間轉移資金、下訂單同時更新庫存和訂單資料表,以及在遊戲中的玩家之間交換項目。
取捨
- 較高的寫入成本
對於高達 1 KB 的項目,相較於標準寫入的 1 WCUs,交易會耗用每個項目 2 個 WCU (一個用於準備,一個用於遞交)。
- 項目限制
單一交易最多可包含一或多個資料表中的 100 個動作。
- 衝突敏感度
如果交易中的任何項目被另一個操作修改,則整個交易會失敗。在高內容案例中,這可能會導致頻繁取消。
實作
下列範例使用 在兩個項目之間TransactWriteItems以原子方式傳輸庫存。如果另一個程序在交易期間修改任一項目,則會復原整個操作。
import boto3 client = boto3.client('dynamodb') def transfer_inventory(source_id, target_id, quantity): try: client.transact_write_items( TransactItems=[ { 'Update': { 'TableName': 'Inventory', 'Key': {'ItemID': {'S': source_id}}, 'UpdateExpression': 'SET QuantityLeft = QuantityLeft - :qty', 'ConditionExpression': 'QuantityLeft >= :qty', 'ExpressionAttributeValues': { ':qty': {'N': str(quantity)} } } }, { 'Update': { 'TableName': 'Inventory', 'Key': {'ItemID': {'S': target_id}}, 'UpdateExpression': 'SET QuantityLeft = QuantityLeft + :qty', 'ExpressionAttributeValues': { ':qty': {'N': str(quantity)} } } } ] ) return True except client.exceptions.TransactionCanceledException as e: print(f"Transaction canceled: {e}") return False
在此範例中,條件表達式會檢查是否存在足夠的庫存,但不需要版本屬性。如果準備和遞交階段之間的另一個操作修改了交易中的任何項目,DynamoDB 會自動取消交易。這就是提供樂觀並行控制的原因 – 交易本身會防止衝突並行修改。
注意
您可以將版本檢查新增為其他條件表達式,以結合交易與樂觀鎖定。這提供額外的保護層,但並非交易偵測衝突的必要條件。
如需詳細資訊,請參閱管理 DynamoDB 交易的複雜工作流程。