Funcionamiento de las Transacciones de Amazon DynamoDB - Amazon DynamoDB

Funcionamiento de las Transacciones de Amazon DynamoDB

Con Amazon DynamoDB Transactions, puede agrupar varias acciones y enviarlas como una sola operación TransactWriteItems o TransactGetItems de tipo "todo o nada". En las secciones siguientes, se describen las operaciones de la API, la administración de la capacidad, las prácticas recomendadas y otros detalles sobre el uso de operaciones transaccionales en DynamoDB.

API TransactWriteItems

TransactWriteItems es una operación de escritura síncrona e idempotente que agrupa hasta 100 acciones de escritura en una única operación de tipo “todo o nada”. Estas acciones pueden estar dirigidas a un máximo de 100 elementos diferenciados en una o varias tablas de DynamoDB en la misma cuenta de AWS y en la misma región. El tamaño total de los elementos de la transacción no puede superar 4 MB. Las acciones se realizan atómicamente, de tal forma que se llevan a cabo correctamente todas o ninguna de ellas.

nota
  • Una operación TransactWriteItems se diferencia de una operación BatchWriteItem en que todas las acciones que contiene deben completarse correctamente o, de lo contrario, no se realiza ningún cambio. Con una operación BatchWriteItem, es posible que solo algunas de las acciones del lote se realicen correctamente y otras, no.

  • Las transacciones no se pueden realizar mediante índices.

No se pueden dirigir varias operaciones de la misma transacción al mismo elemento. Por ejemplo, no se puede realizar una acción ConditionCheck y también una acción Update en el mismo elemento de la misma transacción.

Puede agregar los tipos de acciones siguientes a una transacción:

  • Put: Inicia una operación PutItem para crear un nuevo elemento o sustituir uno antiguo por otro nuevo, ya sea de forma condicional o sin especificar ninguna condición.

  • Update: Inicia una operación UpdateItem para editar los atributos de un elemento existente o agregar un nuevo elemento a la tabla, si no existe ya. Esta acción se utiliza para agregar, eliminar o actualizar atributos a un elemento existente, de forma condicional o sin condiciones.

  • Delete: Inicia una operación DeleteItem para eliminar un solo elemento de una tabla identificado por su clave principal.

  • ConditionCheck: Comprueba la existencia de un elemento o la condición de atributos concretos del elemento.

Una vez que la transacción se completa, los cambios realizados con transacciones se propagan a índices secundarios globales (GSI), secuencias y copias de seguridad. Como la propagación no es inmediata ni instantánea, si se restaura una tabla a partir de una copia de seguridad (RestoreTableFromBackup) o se exporta a un punto en el medio de la propagación (ExportTableToPointInTime), podría contener algunos pero no todos los cambios realizados durante una transacción reciente.

Idempotencia

Opcionalmente, puede incluir un token de cliente al realizar una llamada a TransactWriteItems para asegurarse de que la solicitud sea idempotente. Hacer que las transacciones sean idempotentes ayuda a evitar errores de aplicaciones si se envía la misma operación varias veces debido a una interrupción de la conexión u otro problema de conectividad.

Si la llamada a TransactWriteItems original se realizó correctamente, las llamadas siguientes a TransactWriteItems con el mismo token de cliente también se devolverán correctamente sin hacer ningún cambio. Si se ha establecido el parámetro ReturnConsumedCapacity, la llamada TransactWriteItems inicial devolverá el número de unidades de capacidad de escritura consumidas al realizar los cambios. Las llamadas siguientes a TransactWriteItems con el mismo token de cliente devolverán el número de unidades de capacidad de lectura consumidas al leer el elemento.

Información importante sobre la idempotencia
  • Un token de cliente es válido durante 10 minutos desde que finaliza la solicitud que lo utiliza. Transcurridos esos 10 minutos, cualquier solicitud que use el mismo token de cliente se tratará como si fuera nueva. No debe reutilizar el mismo token de cliente para la misma solicitud si han pasado 10 minutos.

  • Si repite una solicitud con el mismo token de cliente dentro del periodo de idempotencia de 10 minutos, pero cambia algún otro parámetro de la solicitud, DynamoDB devolverá una excepción IdempotentParameterMismatch.

Control de errores de escritura

Las transacciones de escritura no se realizarán correctamente en las siguientes circunstancias:

  • Cuando no se cumple alguna de las condiciones de las expresiones de condición.

  • Cuando se produce un error de validación de transacción porque hay más de una acción dirigida al mismo elemento en una sola operación TransactWriteItems.

  • Cuando una solicitud TransactWriteItems está en conflicto con una operación TransactWriteItems en curso para uno o varios elementos de la solicitud TransactWriteItems. En este caso, la solicitud genera un error TransactionCanceledException.

  • Cuando no hay suficiente capacidad aprovisionada para completar la transacción.

  • Cuando el tamaño de un elemento es excesivo (más de 400 KB), un índice secundario local (LSI) se vuelve demasiado grande o se produce algún error de validación semejante a causa de los cambios realizados por la transacción.

  • Cuando hay algún error de usuario, como un formato de datos no válido.

Para obtener más información acerca de cómo se manejan los conflictos con operaciones TransactWriteItems, consulte Gestión de conflictos de transacciones en DynamoDB.

API TransactGetItems

TransactGetItems es una operación de lectura síncrona que agrupa hasta 100 acciones Get. Estas acciones pueden estar dirigidas a un máximo de 100 elementos diferenciados en una o varias tablas de DynamoDB en la misma cuenta y región de AWS. El tamaño total de los elementos de la transacción no puede superar 4 MB.

Las acciones Get se realizan atómicamente, de tal forma que se llevan a cabo correctamente todas o ninguna de ellas:

  • Get: Inicia una operación GetItem para recuperar un conjunto de atributos para el elemento que tiene la clave principal especificada. Si no se encuentra ningún elemento que coincida, Get no devuelve ningún dato.

Control de errores de lectura

Las transacciones de lectura no se realizarán correctamente en las siguientes circunstancias:

  • Cuando una solicitud TransactGetItems está en conflicto con una operación TransactWriteItems en curso para uno o varios elementos de la solicitud TransactGetItems. En este caso, la solicitud genera un error TransactionCanceledException.

  • Cuando no hay suficiente capacidad aprovisionada para completar la transacción.

  • Cuando hay algún error de usuario, como un formato de datos no válido.

Para obtener más información acerca de cómo se manejan los conflictos con operaciones TransactGetItems, consulte Gestión de conflictos de transacciones en DynamoDB.

Niveles de aislamiento para las transacciones de DynamoDB

Los niveles de aislamiento de las operaciones transaccionales (TransactWriteItems o TransactGetItems) y otras operaciones son los siguientes.

SERIALIZABLE

El aislamiento serializable garantiza que los resultados de varias operaciones concurrentes sean iguales que si ninguna operación se hubiera iniciado antes de finalizar la anterior.

Existe aislamiento serializable entre los siguientes tipos de operaciones:

  • Entre cualquier operación transaccional y cualquier operación de escritura estándar (PutItem, UpdateItem o DeleteItem).

  • Entre cualquier operación transaccional y cualquier operación de lectura estándar (GetItem).

  • Entre una operación TransactWriteItems y una operación TransactGetItems.

Aunque existe aislamiento serializable entre las operaciones transaccionales y cada escritura estándar individual escribe en una operación BatchWriteItem, no se produce aislamiento serializable entre la transacción y la operación BatchWriteItem como una unidad.

Del mismo modo, el nivel de aislamiento entre una operación transaccional y una operación GetItems individual de una operación BatchGetItem es serializable. Pero el nivel de aislamiento entre la transacción y la operación BatchGetItem como unidad es de lectura confirmada.

Una sola solicitud GetItem es serializable con respecto a una solicitud TransactWriteItems de una de las dos formas siguientes: antes o después de la solicitud TransactWriteItems. Multiple solicitudes GetItem, de las claves en solicitudes TransactWriteItems se pueden ejecutar en cualquier orden, y por lo tanto los resultados son lectura confirmada.

Por ejemplo, si las solicitudes GetItem para el elemento A y el elemento B se ejecutan simultáneamente con una solicitud TransactWriteItems que modifica tanto el punto A como el punto B, hay cuatro posibilidades:

  • Ambos GetItem se ejecutan antes de que la solicitud TransactWriteItems.

  • Ambos GetItem se ejecutan después de la solicitud TransactWriteItems.

  • Solicitud GetItem para el elemento A se ejecuta antes de la solicitud TransactWriteItems. Para el elemento B, GetItem se ejecuta después de TransactWriteItems.

  • Solicitud GetItem para el elemento B se ejecuta antes de la solicitud TransactWriteItems. Para el elemento A, GetItem se ejecuta después de TransactWriteItems.

Utilice TransactGetItems, si prefiere el nivel de aislamiento serializable para múltiples solicitudes GetItem.

Si se realiza una lectura no transaccional de varios elementos que formaban parte de la misma solicitud de escritura de transacción durante el vuelo, es posible que pueda leer el nuevo estado de algunos de los elementos y el estado anterior de los demás. Solo podrá leer el nuevo estado de todos los elementos que formaban parte de la solicitud de escritura de la transacción cuando reciba una respuesta correcta a la escritura de la transacción.

LECTURA CONFIRMADA

El aislamiento de lectura confirmada garantiza que las operaciones de lectura siempre devuelven valores confirmados para un elemento: la lectura nunca presentará una vista al elemento que represente un estado de una escritura transaccional que no haya tenido éxito finalmente. El aislamiento de lectura confirmada no impide las modificaciones del elemento inmediatamente después de la operación de lectura.

El nivel de aislamiento es de lectura confirmada entre cualquier operación transaccional y cualquier operación de lectura que conlleve varias lecturas estándar (BatchGetItem, Query o Scan). Si una escritura transaccional actualiza un elemento en medio de una operación de BatchGetItem, Query o Scan, la parte posterior de la operación de lectura devuelve el nuevo valor confirmado (con ConsistentRead) o posiblemente un valor confirmado anterior [lecturas coherentes posteriores]).

Resumen de la operación

A modo de resumen, en la siguiente tabla se indican los niveles de aislamiento entre una operación transaccional (TransactWriteItems o TransactGetItems) y otras operaciones.

Operación Nivel de aislamiento

DeleteItem

Serializable

PutItem

Serializable

UpdateItem

Serializable

GetItem

Serializable

BatchGetItem

Lectura confirmada*

BatchWriteItem

NO serializable*

Query

Lectura confirmada

Scan

Lectura confirmada

Otra operación transaccional

Serializable

Los niveles marcados con un asterisco (*) se aplican a la operación como una unidad. Sin embargo, las acciones individuales contenidas en esas operaciones tienen el nivel de aislamiento serializable.

Gestión de conflictos de transacciones en DynamoDB

Un conflicto de transacciones puede producirse durante solicitudes concurrentes de nivel de elemento en un elemento dentro de una transacción. Los conflictos de transacciones pueden producirse en los siguientes escenarios:

  • Una solicitud PutItem, UpdateItem o DeleteItem de un elemento entra en conflicto con una solicitud TransactWriteItems en curso que incluye el mismo elemento.

  • Un elemento incluido en una solicitud TransactWriteItems forma parte de otra solicitud TransactWriteItems en curso.

  • Un elemento incluido en una solicitud TransactGetItems forma parte de otra solicitud TransactWriteItems, BatchWriteItem, PutItem, UpdateItem o DeleteItem en curso.

nota
  • Cuando se rechaza una solicitud PutItem, UpdateItem o DeleteItem, la solicitud no se realiza correctamente y genera una excepción TransactionConflictException.

  • Si se rechaza cualquier solicitud de nivel de elemento dentro de una operación TransactWriteItems o TransactGetItems, la solicitud no se realiza correctamente y genera una excepción TransactionCanceledException. Si esa solicitud falla, los SDK de AWS no vuelven a intentar la solicitud.

    Si se está utilizando el AWS SDK for Java, la excepción contiene la lista de CancellationReasons, ordenada según la lista de elementos del parámetro TransactItems de la solicitud. Para los demás lenguajes, se incluye una representación de cadena de la lista en el mensaje de error de la excepción.

  • Si una operación TransactWriteItems o TransactGetItems está en conflicto con una solicitud GetItem concurrente, las dos operaciones podrían realizarse correctamente.

La métrica TransactionConflict de CloudWatch se incrementa para cada solicitud de nivel de elemento que no se realiza correctamente.

Uso de las API transaccionales en DynamoDB Accelerator (DAX)

Tanto TransactWriteItems como TransactGetItems se admiten en DynamoDB Accelerator (DAX) con los mismos niveles de aislamiento que en DynamoDB.

TransactWriteItems escribe a través de DAX. DAX pasa una llamada TransactWriteItems a DynamoDB y devuelve la respuesta. Para rellenar la caché después de la escritura, DAX llama a TransactGetItems en segundo plano para cada elemento en la operación TransactWriteItems, que consume unidades de capacidad de lectura adicionales. (Para obtener más información, consulte Administración de la capacidad para las transacciones). Esta funcionalidad le permite no complicar la lógica de la aplicación y utilizar DAX para operaciones transaccionales así como para operaciones no transaccionales.

Las llamadas TransactGetItems se pasan por DAX sin que los elementos se almacenen en caché localmente. Es el mismo comportamiento que tienen las API de lectura de consistencia alta en DAX.

Administración de la capacidad para las transacciones

Habilitar las transacciones para las tablas de DynamoDB no conlleva ningún coste adicional. Usted paga sólo por las lecturas o escrituras que forman parte de su transacción. DynamoDB lleva a cabo dos lecturas o escrituras subyacentes de cada elemento de la transacción: una para preparar la transacción y otra para confirmarla. Las dos operaciones de lectura/escritura subyacentes están visibles en las métricas de Amazon CloudWatch.

Planee las lecturas y escrituras adicionales que requieren las API transaccionales al aprovisionar la capacidad para las tablas. Por ejemplo, supongamos que su aplicación ejecuta una transacción por segundo y que cada transacción escribe tres elementos de 500 bites en la tabla. Cada elemento requiere dos unidades de capacidad de escritura (WCU): una para preparar la transacción y otra para confirmarla. Por consiguiente, tendría que aprovisionar seis WCU para la tabla.

Si utilizó DynamoDB Accelerator (DAX) en el ejemplo anterior, también debió utilizar dos unidades de capacidad de lectura (RCU) para cada elemento de la llamada TransactWriteItems. Por tanto, tendría que aprovisionar seis RCU adicionales para la tabla.

Del mismo modo, si la aplicación ejecuta una transacción de lectura por segundo y cada transacción lee tres elementos de 500 bytes de la tabla, debería aprovisionar seis unidades de capacidad de lectura (RCU) para la tabla. La lectura de cada elemento requiere dos RCU: una para preparar la transacción y otra para confirmarla.

Además, el comportamiento predeterminado del SDK consiste en reintentar las transacciones si se produce alguna excepción TransactionInProgressException. Planee las unidades de capacidad de lectura (RCU) adicionales que consumen estos reintentos. Lo mismo sucede si reintenta transacciones de su propio código mediante un ClientRequestToken.

Prácticas recomendadas para las transacciones

Es importante tener en cuenta las prácticas recomendadas siguientes al utilizar transacciones de DynamoDB.

  • Habilite el escalado automático en las tablas o asegúrese de haber aprovisionado suficiente capacidad de rendimiento para llevar a cabo las dos operaciones de lectura o escritura para cada elemento de la transacción.

  • Si no utiliza un SDK proporcionado por AWS, incluya un atributo ClientRequestToken al realizar una llamada a TransactWriteItems para asegurarse de que la solicitud sea idempotente.

  • No agrupe las operaciones en una transacción si no es necesario. Por ejemplo, si una misma transacción compuesta de 10 operaciones se puede desglosar en varias transacciones de modo que la aplicación continúe siendo correcta, recomendamos dividir la transacción. Usar transacciones más sencillas mejora el rendimiento y aumenta la probabilidad de que se ejecuten correctamente.

  • Si varias transacciones actualizan los mismos elementos de forma simultánea, pueden provocar conflictos que cancelen las transacciones. Recomendamos las siguientes prácticas recomendadas de DynamoDB para modelar los datos de tal forma que se reduzcan al mínimo esos conflictos.

  • Si un conjunto de atributos se actualiza a menudo para varios elementos durante una misma transacción, puede ser conveniente agrupar los atributos en un solo elemento para reducir el ámbito de la transacción.

  • Evite utilizar transacciones para la ingesta masiva de datos. Para las escrituras masivas, es preferible usar BatchWriteItem.

Uso de las API transaccionales con tablas globales

Las operaciones incluidas en una transacción de DynamoDB solo se garantizan como transaccionales en la región en la que se ha ejecutado originalmente la transacción. La transaccionalidad no se conserva cuando los cambios aplicados a una transacción se replican en todas las regiones en réplicas de tablas globales.

Transacciones de DynamoDB en comparación con la biblioteca de transacciones del cliente de AWSLabs

Las transacciones de DynamoDB proporcionan una forma más rentable, robusta y eficiente de sustituir la biblioteca de cliente de transacciones de AWSLabs. Sugerimos actualizar las aplicaciones de modo que utilicen las API de transacciones nativas del lado del servidor.