

# Amazon DynamoDB Transactions: como funciona
<a name="transaction-apis"></a>

Com as Amazon DynamoDB Transactions, você pode agrupar várias ações juntas e enviá-las como uma única operação tudo ou nada `TransactWriteItems` ou `TransactGetItems`. As seções a seguir descrevem operações de API, gerenciamento de capacidade, práticas recomendadas e outros detalhes sobre o uso de operações transacionais no DynamoDB.

**Topics**
+ [API TransactWriteItems](#transaction-apis-txwriteitems)
+ [API TransactGetItems](#transaction-apis-txgetitems)
+ [Níveis de isolamento para transações do DynamoDB](#transaction-isolation)
+ [Tratamento de conflitos em transações com o DynamoDB](#transaction-conflict-handling)
+ [Usar APIs transacionais no DynamoDB Accelerator (DAX)](#transaction-apis-dax)
+ [Gerenciar capacidade para transações](#transaction-capacity-handling)
+ [Práticas recomendadas para transações](#transaction-best-practices)
+ [Usar APIs Transacionais com tabelas globais](#transaction-integration)
+ [Transações do DynamoDB comparadas com biblioteca de clientes de transações do AWSLabs](#transaction-vs-library)

## API TransactWriteItems
<a name="transaction-apis-txwriteitems"></a>

`TransactWriteItems` é uma operação de gravação síncrona e idempotente que agrupa até 100 ações de gravação em uma única operação tudo ou nada. Essas ações podem ter como destino até 100 itens distintos em uma ou mais tabelas do DynamoDB na mesma conta e região da AWS. O tamanho agregado dos itens na transação não podem exceder 4 MB. As ações são concluídas de forma atômica para que todas sejam bem-sucedidas ou nenhuma tenha êxito.

**nota**  
 Uma operação `TransactWriteItems` difere de uma operação `BatchWriteItem` em que todas as ações contidas devem ser concluídas com êxito, ou nenhuma alteração foi feita. Com uma operação `BatchWriteItem`, é possível que apenas as ações no lote sejam bem-sucedidas enquanto as outras não. 
 As transações não podem ser realizadas usando índices. 

Você não pode visar o mesmo item com várias operações dentro da mesma transação. Por exemplo, você não pode executar uma ação `ConditionCheck` e também uma `Update` no mesmo item na mesma transação.

Você pode adicionar os tipos a seguir de ações a uma transação:
+ `Put`: inicia uma operação `PutItem` para criar um novo item ou substituir um item antigo com um item novo, de forma condicional ou sem especificar qualquer condição.
+ `Update`: inicia uma operação `UpdateItem` para editar um atributo de item existente ou adicionar um novo item à tabela se ele já não existir. Use essa ação para adicionar, excluir ou atualizar atributos ou um item existente de forma condicional ou sem uma condição.
+ `Delete`: inicia uma operação `DeleteItem` para excluir um único item em uma tabela identificada por essa chave principal.
+ `ConditionCheck`: verifica se um item existe ou verifica a condição de atributos específicos do item.

Quando uma transação é concluída no DynamoDB, suas alterações começam a se propagar para índices secundários globais (GSIs), fluxos e backups. Essa propagação ocorre gradualmente: registros de fluxo da mesma transação podem aparecer em momentos diferentes e podem ser intercalados com registros de outras transações. Os consumidores do fluxo não devem presumir a atomicidade da transação ou as garantias de ordenação.

Para garantir um snapshot atômico dos itens modificados em uma transação, use a operação TransactGetItems para ler todos os itens relevantes juntos. Essa operação fornece uma visão consistente dos dados, garantindo que você veja todas as alterações de uma transação concluída ou nenhuma.

Como a propagação não é imediata, se uma tabela for restaurada do backup ([RestoreTableFromBackup](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_RestoreTableFromBackup.html)) ou exportada para um ponto anterior no tempo ([ExportTableToPointInTime](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ExportTableToPointInTime.html)) no meio da transação, ela poderá conter apenas algumas das alterações feitas durante uma transação recente.

### Potência igual
<a name="transaction-apis-txwriteitems-idempotency"></a>

Você pode, opcionalmente, incluir um token de cliente quando fizer uma chamada `TransactWriteItems` para garantir que a solicitação é *idempotente*. Realizar transações idempotentes ajuda a prevenir erros de aplicação se a mesma operação for enviada diversas vezes por conta de uma desconexão ou outro problema de conexão.

Se a chamada `TransactWriteItems` original for bem-sucedida, as chamadas `TransactWriteItems` subsequentes com o mesmo token de cliente retornarão com êxito sem nenhuma alteração. Se o parâmetro `ReturnConsumedCapacity` estiver definido, a chamada `TransactWriteItems` inicial retornará o número de unidades de capacidade de gravação consumidas para realizar as alterações. Chamadas `TransactWriteItems` subsequentes com o mesmo token de cliente devolvem o número de unidades de capacidade de leitura consumidas na leitura do item.

**Pontos importantes sobre idempotência**
+ Um token de cliente é válido por 10 minutos após a solicitação utilizada acabar. Depois de 10 minutos, quaisquer solicitações que usarem o mesmo token de cliente são tratadas como uma nova solicitação. Você não deve reutilizar o mesmo token de cliente para a mesma solicitação após 10 minutos.
+ Se você repetir uma solicitação com o mesmo token de cliente dentro de 10 minutos na janela de idempotência, mas alterar algum parâmetro de solicitação, o DynamoDB retornará uma exceção `IdempotentParameterMismatch`.

### Tratamento de erros para gravação
<a name="transaction-apis-txwriteitems-errors"></a>

Transações de gravação não são bem-sucedidas nas circunstâncias a seguir:
+ Quando uma condição em uma das expressões de condição não é alcançada.
+ Quando uma validação de transação ocorrer por conta de mais de uma ação na mesma operação `TransactWriteItems` ter como destino o mesmo item.
+ Quando uma solicitação `TransactWriteItems` entra em conflito com uma operação `TransactWriteItems` em andamento em um ou mais itens na operação `TransactWriteItems`. Nesse caso, a solicitação falha com um `TransactionCanceledException`.
+ Quando há capacidade provisionada insuficiente para a transação ser concluída.
+ Quando o tamanho de um item é muito maior (maior que 400 KB), ou um índice secundário local (LSI) se torna muito grande, ou um erro de validação semelhante ocorre por conta das alterações feitas pela transação.
+ Quando houver um erro de usuário, como formato de dados inválidos.

 Para obter mais informações sobre como os conflitos com operações `TransactWriteItems` são gerenciados, consulte [Tratamento de conflitos em transações com o DynamoDB](#transaction-conflict-handling).

## API TransactGetItems
<a name="transaction-apis-txgetitems"></a>

`TransactGetItems` é uma operação de leitura síncrona que agrupa até 100 ações `Get`. Essas ações podem ter como destino até 100 itens distintos em uma ou mais tabelas do DynamoDB na mesma conta e região da AWS. O tamanho agregado dos itens na transação não pode exceder 4 MB. 

As ações `Get` são realizadas de forma atômica para que todas sejam bem-sucedidas ou nenhuma tenha êxito:
+ `Get`: inicia uma operação `GetItem` para recuperar um conjunto de atributos do item com a chave primária fornecida. Se não houver item correspondente, `Get` não retornará quaisquer dados.

### Tratamento de erros para leitura
<a name="transaction-apis-txgetitems-errors"></a>

Transações de leitura não são bem-sucedidas nas circunstâncias a seguir:
+ Quando uma solicitação `TransactGetItems` entra em conflito com uma operação `TransactWriteItems` em andamento em um ou mais itens na operação `TransactGetItems`. Nesse caso, a solicitação falha com um `TransactionCanceledException`.
+ Quando há capacidade provisionada insuficiente para a transação ser concluída.
+ Quando houver um erro de usuário, como formato de dados inválidos.

 Para obter mais informações sobre como os conflitos com operações `TransactGetItems` são gerenciados, consulte [Tratamento de conflitos em transações com o DynamoDB](#transaction-conflict-handling).

## Níveis de isolamento para transações do DynamoDB
<a name="transaction-isolation"></a>

Os níveis de isolamento de operações transacionais (`TransactWriteItems` ou `TransactGetItems`) e outras operações são os seguintes.

### SERIALIZÁVEL
<a name="transaction-isolation-serializable"></a>

Isolamento *Serializável* garante que os resultados de várias operações concomitantes sejam os mesmos como se nenhuma operação começar com o anterior finalizado.

Há um isolamento serializável entre os tipos a seguir de operação:
+ Entre qualquer operação transacional e qualquer padrão de operação de gravação (`PutItem`, `UpdateItem` ou `DeleteItem`).
+ Entre qualquer operação transacional e qualquer padrão de operação de leitura (`GetItem`).
+ Entre uma operação `TransactWriteItems` e `TransactGetItems`.

Apesar de haver isolamento serializável entre operações transacionais, e cada padrão individual de gravação em uma operação `BatchWriteItem`, não há isolamento serializável entre a transação e a operação `BatchWriteItem` como uma unidade.

De modo semelhante, o nível de isolamento entre uma operação transacional e `GetItems` individual em uma operação `BatchGetItem` é serializável. Porém, o nível de isolamento entre a transação e a operação `BatchGetItem` como uma unidade é *confirmado para leitura*.

Uma única solicitação `GetItem` é serializável em relação a uma solicitação `TransactWriteItems` de duas formas, antes ou depois da solicitação `TransactWriteItems`. Várias solicitações `GetItem`, contra chaves em solicitações `TransactWriteItems`, podem ser executadas em qualquer ordem e, portanto, os resultados são *confirmado para leitura*.

Por exemplo, se solicitações `GetItem` para o item A e o item B forem executadas simultaneamente com uma solicitação `TransactWriteItems` que modifica o item A e o item B, existem quatro possibilidades:
+ Ambas as solicitações `GetItem` são executadas antes da solicitação `TransactWriteItems`.
+ Ambas as solicitações `GetItem` são executadas após a solicitação `TransactWriteItems`.
+ A solicitação `GetItem` para o item A é executada antes da solicitação `TransactWriteItems`. Para o item B, `GetItem` é executada após `TransactWriteItems`.
+ A solicitação `GetItem` para o item B é executada antes da solicitação `TransactWriteItems`. Para o item A, `GetItem` é executada após `TransactWriteItems`.

Você deverá usar `TransactGetItems` se preferir o nível de isolamento serializável para várias solicitações `GetItem`.

Se uma leitura não transacional for feita em vários itens que faziam parte da mesma solicitação de gravação de transação em andamento, é possível que você consiga ler o novo estado de alguns dos itens e o estado antigo dos outros itens. Você poderá ler o novo estado de todos os itens que faziam parte da solicitação de gravação da transação somente quando uma resposta bem-sucedida for recebida para a gravação transacional, indicando que a transação foi concluída.

Depois que a transação for concluída com êxito e uma resposta for recebida, as operações de leitura *finalmente consistente* subsequentes ainda poderão exibir o estado antigo por um curto período devido ao modelo de consistência final do DynamoDB. Para garantir a leitura dos dados mais atualizados imediatamente após uma transação, você deve usar leituras [*altamente consistentes*](HowItWorks.ReadConsistency.md#HowItWorks.ReadConsistency.Strongly) definindo `ConsistentRead` como verdadeiro.

### CONFIRMADO PARA LEITURA
<a name="transaction-isolation-read-committed"></a>

O isolamento *confirmado para leitura* garante que as operações de leitura sempre retornem valores confirmados para um item; a leitura nunca apresentará uma visualização do item representando um estado de uma gravação transacional que não teve êxito final. Isolamento confirmado para leitura não previne modificações do item imediatamente após operação de leitura.

O nível de isolamento é confirmado para leitura entre qualquer operação transacional e qualquer operação de leitura que envolva vários padrões de leitura (`BatchGetItem`, `Query` ou `Scan`). Se uma gravação transacional atualizar um item no meio de uma operação de `BatchGetItem`, `Query` ou `Scan`, a parte subsequente da operação de leitura retornará o novo valor confirmado [com `ConsistentRead)` ou possivelmente um valor confirmado anteriormente (leitura final consistente)].

### Resumo da operação
<a name="transaction-isolation-table"></a>

Para resumir, a tabela a seguir mostra os níveis de isolamento entre uma operação transacional (`TransactWriteItems` ou `TransactGetItems`) e outras operações.


| Operation | Nível de isolamento | 
| --- | --- | 
| `DeleteItem` | *Serializável* | 
| `PutItem` | *Serializável* | 
| `UpdateItem` | *Serializável* | 
| `GetItem` | *Serializável* | 
| `BatchGetItem` | *Confirmado para leitura*\* | 
| `BatchWriteItem` | *NÃO serializável*\* | 
| `Query` | *Confirmado para leitura* | 
| `Scan` | *Confirmado para leitura* | 
| Outra operação transacional | *Serializável* | 

Níveis marcados com asterisco (\*) aplicam-se à operação como uma unidade. No entanto, ações individuais dentro dessas operações tem um nível de isolamento *serializável*.

## Tratamento de conflitos em transações com o DynamoDB
<a name="transaction-conflict-handling"></a>

Um conflito de transação pode correr em solicitações simultâneas no nível do item, em um item dentro de uma transação. Os conflitos de transação podem ocorrer nos seguintes casos: 
+ Uma solicitação `PutItem`, `UpdateItem` ou `DeleteItem` de um item conflita com uma solicitação `TransactWriteItems` em andamento que inclui o mesmo item.
+ Um item dentro de uma solicitação `TransactWriteItems` é parte de outra solicitação `TransactWriteItems` em andamento.
+ Um item dentro de uma solicitação `TransactGetItems` é parte de outra solicitação `TransactWriteItems`, `BatchWriteItem`, `PutItem`, `UpdateItem` ou `DeleteItem` em andamento.

**nota**  
Quando uma solicitação `PutItem`, `UpdateItem` ou `DeleteItem` é rejeitada, a solicitação falha com um `TransactionConflictException`, 
Se qualquer solicitação no nível do item dentro de `TransactWriteItems` ou `TransactGetItems` é rejeitada, a solicitação falha com um `TransactionCanceledException`. Se essa solicitação falhar, os AWS SDKs não tentarão repetir a solicitação.  
Se você estiver usando AWS SDK para Java, a exceção conterá a lista de [CancellationReasons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CancellationReason.html), em ordem de acordo com a lista de itens no parâmetro de solicitação `TransactItems`. Para outros idiomas, uma representação em string da lista é incluída na mensagem de erro de exceção. 
Se uma operação `TransactWriteItems` ou `TransactGetItems` em andamento entrar em conflito com uma solicitação `GetItem` simultânea, as duas podem ter êxito.

A métrica [TransactionConflict do CloudWatch](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/metrics-dimensions.html) é incrementada em cada solicitação que falhou no nível do item

## Usar APIs transacionais no DynamoDB Accelerator (DAX)
<a name="transaction-apis-dax"></a>

O DynamoDB Accelerator (DAX) oferece suporte a `TransactWriteItems` e `TransactGetItems` com os mesmos níveis de isolamento que no DynamoDB.

`TransactWriteItems` grava via DAX. O DAX passa uma chamada `TransactWriteItems` para o DynamoDB e retorna a resposta. Para preencher o cache após a gravação, o DAX chama `TransactGetItems` em segundo plano para cada item na operação `TransactWriteItems`, o que consome unidades de capacidade de leitura adicionais. (Para ter mais informações, consulte [Gerenciar capacidade para transações](#transaction-capacity-handling).) Essa funcionalidade permite manter simples a lógica da aplicação e usar o DAX para operações transacionais e não transacionais.

`TransactGetItems`Chamadas de são transmitidas pelo DAX sem que os itens sejam armazenados em cache localmente. É o mesmo comportamento para APIs de leitura fortemente consistente no DAX.

## Gerenciar capacidade para transações
<a name="transaction-capacity-handling"></a>

Não há custo adicional para habilitar transações para suas tabelas do DynamoDB. Você paga apenas pelas leituras ou gravações que fazem parte de sua transação. O DynamoDB realiza duas leituras subjacentes ou gravações de cada item na transação: uma para preparar a transação e outra para enviar a transação. Essas duas operações de leitura/gravação subjacente são visíveis nas métricas do Amazon CloudWatch.

Planeje para leituras e gravações adicionais que são necessárias por APIs transacionais ao provisionar a capacidade de suas tabelas. Por exemplo, suponha que sua aplicação execute uma transação por segundo e cada transação grave itens de 500 bytes em sua tabela. Cada item requer duas capacidades de gravação (WCUs): uma para preparar a transação e uma para enviar a transação. Portanto, você precisa provisionar seis WCUs na tabela. 

Se você usar o DynamoDB Accelerator (DAX) no exemplo anterior, use também as unidades de capacidade de leitura (RCUs) em cada item na chamada `TransactWriteItems`. Então, você precisa provisionar seis RCUs adicionais na tabela.

De forma semelhante, se sua aplicação executa uma transação de leitura por segundo, e cada transação lê itens de 500 bytes na sua tabela, é preciso prover seis unidades de capacidade de leitura (RCUs) na tabela. A leitura de cada item requer duas RCUs: uma para preparar a transação e uma para enviar a transação.

Além disso, comportamento de SDK padrão é tentar transações novamente em caso de uma exceção `TransactionInProgressException`. Planeje para as unidades de capacidade de leitura adicional (RCUs) que essas tentativas repetitivas consumem. O mesmo é verdade se você estiver tentando novamente transações em seu código usando um `ClientRequestToken`.

## Práticas recomendadas para transações
<a name="transaction-best-practices"></a>

Considere as seguintes práticas recomendadas ao usar transações do DynamoDB.
+ Habilitar Auto Scaling nas suas tabelas, ou garantir que você tem capacidade de throughput suficiente para realizar as duas operações de leitura ou gravação em cada item na transação.
+ Se não estiver usando um SDK fornecido pela AWS, inclua um atributo `ClientRequestToken` quando realizar uma chamada `TransactWriteItems` para garantir que a solicitação é idempotente.
+ Não agrupe operações em uma transação se não for necessário. Por exemplo, se uma transação única com 10 operações puder ser separada em várias transações sem comprometimento da exatidão do aplicativo, recomendamos separar a transação. Transações mais simples melhorar a taxa de transferência e têm maior chance de êxito. 
+ Transações múltiplas atualizando os mesmos itens simultaneamente podem causar conflitos que cancelam as transações. Recomendamos as práticas recomendadas do DynamoDB a seguir para modelagem de dados a fim de minimizar esses conflitos.
+ Se um conjunto de atributos for frequentemente atualizado entre vários itens como parte de uma única transação, considere agrupar os atributos em um único item para reduzir o escopo da transação.
+ Evite usar transações para adicionar dados no grupo. Para gravações em grupo, é melhor usar `BatchWriteItem`.

## Usar APIs Transacionais com tabelas globais
<a name="transaction-integration"></a>

As operações transacionais oferecem garantia de atomicidade, consistência, isolamento e durabilidade (ACID) somente na região da AWS em que a API de gravação foi invocada. As transações não são compatíveis entre regiões em tabelas globais. Por exemplo, suponha que você tenha uma tabela global com réplicas nas regiões Leste dos EUA (Ohio) e Oeste dos EUA (Oregon) e execute uma operação `TransactWriteItems` na região Leste dos EUA (Norte da Virgínia). Você pode observar transações parcialmente concluídas na região Oeste dos EUA (Oregon) conforme as alterações são replicadas. As alterações só serão replicadas para outras regiões quando forem confirmadas na região de origem.

## Transações do DynamoDB comparadas com biblioteca de clientes de transações do AWSLabs
<a name="transaction-vs-library"></a>

As transações do DynamoDB fornecem uma substituição mais eficiente em termos de custos, efetiva e com maior performance para as transações da biblioteca de clientes do [AWSLabs](https://github.com/awslabs). Sugerimos atualizar os aplicativos para usar com as APIs de transação do lado do servidor nativas.