

# Bloqueo negativo con las transacciones de DynamoDB
<a name="BestPractices_PessimisticLocking"></a>

Las [transacciones](transactions.md) de DynamoDB ofrecen un enfoque de todo o nada para las operaciones agrupadas. Cuando usa `TransactWriteItems`, DynamoDB supervisa todos los artículos de la transacción. Si alguna operación modifica algún elemento durante la transacción, se cancela toda la transacción y DynamoDB devuelve una `TransactionCanceledException`. Este comportamiento proporciona una forma de control de la simultaneidad negativo, ya que las modificaciones simultáneas conflictivas se previenen en lugar de detectarse a posteriori.

## Cuándo utilizar las transacciones para el bloqueo
<a name="BestPractices_PessimisticLocking_WhenToUse"></a>

Las transacciones son una buena opción cuando:
+ Debe actualizar varios elementos de forma atómica, ya sea dentro de la misma tabla o en varias tablas.
+ La lógica empresarial requiere una semántica de todo o nada, o bien todos los cambios se realizan correctamente o no se aplica ninguno.

Algunos ejemplos habituales son la transferencia de fondos entre cuentas, la realización de pedidos que actualizan el inventario y las tablas de pedidos y el intercambio de elementos entre los jugadores de un juego.

## Desventajas
<a name="BestPractices_PessimisticLocking_Tradeoffs"></a>

**Mayor costo de escritura**  
Para los elementos de hasta 1 KB, las transacciones consumen 2 WCU por elemento (una para preparar y otra para confirmar), en comparación con 1 WCU para una escritura estándar.

**Límite de elementos**  
Una transacción puede incluir hasta 100 acciones en una o varias tablas.

**Sensibilidad a los conflictos**  
Si otra operación modifica algún elemento de la transacción, toda la transacción produce un error. En situaciones de alta contención, esto puede provocar cancelaciones frecuentes.

## Implementación
<a name="BestPractices_PessimisticLocking_Implementation"></a>

En el siguiente ejemplo, se utiliza `TransactWriteItems` para transferir el inventario entre dos elementos de forma atómica. Si otro proceso modifica alguno de los elementos durante la transacción, se anula toda la operación.

```
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
```

En este ejemplo, la expresión de condición comprueba que existe suficiente inventario, pero no se necesita ningún atributo de versión. DynamoDB cancela automáticamente la transacción si otra operación modifica algún elemento de la transacción entre las fases de preparación y confirmación. Esto es lo que proporciona el control de simultaneidad negativo, la propia transacción evita las modificaciones simultáneas conflictivas.

**nota**  
Puede combinar transacciones con un bloqueo positivo agregando verificaciones de versión como expresiones de condición adicionales. Esto proporciona una capa adicional de protección, pero no es necesario para que la transacción detecte conflictos.

Para obtener más información, consulte [Administración de flujos de trabajo complejos con transacciones de DynamoDB](transactions.md).