

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

# 使用 DynamoDB 交易進行估算鎖定
<a name="BestPractices_PessimisticLocking"></a>

DynamoDB [交易](transactions.md)提供all-or-nothing方法。當您使用 時`TransactWriteItems`，DynamoDB 會監控交易中的所有項目。如果在交易期間由其他操作修改任何項目，則整個交易都會取消，且 DynamoDB 會傳回 `TransactionCanceledException`。這種行為提供一種可觀的並行控制形式，因為防止衝突並行修改，而不是在事實之後偵測到。

## 何時使用交易進行鎖定
<a name="BestPractices_PessimisticLocking_WhenToUse"></a>

在下列情況下，交易非常適合：
+ 您需要以原子方式更新多個項目，無論是在同一資料表內或跨資料表。
+ 您的商業邏輯需要all-or-nothing語意 - 所有變更都成功套用或不套用。

常見範例包括在帳戶之間轉移資金、下訂單同時更新庫存和訂單資料表，以及在遊戲中的玩家之間交換項目。

## 取捨
<a name="BestPractices_PessimisticLocking_Tradeoffs"></a>

**較高的寫入成本**  
對於高達 1 KB 的項目，相較於標準寫入的 1 WCUs，交易會耗用每個項目 2 個 WCU （一個用於準備，一個用於遞交）。

**項目限制**  
單一交易最多可包含一或多個資料表中的 100 個動作。

**衝突敏感度**  
如果交易中的任何項目被另一個操作修改，則整個交易會失敗。在高內容案例中，這可能會導致頻繁取消。

## 實作
<a name="BestPractices_PessimisticLocking_Implementation"></a>

下列範例使用 在兩個項目之間`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 交易的複雜工作流程](transactions.md)。