Isolamento e capacidade de serialização de transações

Nesta página, descrevemos o isolamento, a capacidade de serialização e a disputa de dados transacionais. Para ver exemplos de códigos de transações, consulte transações e gravações em lote.

Transações e disputa de dados

Para que uma transação seja bem-sucedida, os documentos recuperados pelas operações de leitura precisam permanecer inalterados por operações fora da transação. Se outra operação tentar alterar um desses documentos, as operações entrarão em um estado de disputa de dados com a transação.

Disputa de dados
Quando duas ou mais operações competem para controlar o mesmo documento. Por exemplo, uma transação pode exigir que um documento permaneça consistente enquanto uma operação simultânea tenta atualizar valores de campos desse documento.

O Cloud Firestore resolve a contenção de dados atrasando ou apresentando falhas em uma das operações. As bibliotecas de cliente do Cloud Firestore repetem automaticamente as transações que falham devido à contenção de dados. Após um número finito de novas tentativas, a operação de transação falha e retorna uma mensagem de erro:

ABORTED: Too much contention on these documents. Please try again.

Ao decidir qual operação terá uma falha ou sofrerá um atraso, o comportamento depende do tipo de controles de simultaneidade.

Controles de simultaneidade

O modo de simultaneidade é uma opção de banco de dados configurável. O Cloud Firestore é compatível com os seguintes modos de simultaneidade:

  • PESSIMISTIC: os controles de simultaneidade pessimistas presumem que a disputa de dados é provável. Essas transações usam bloqueios do banco de dados para evitar que outras operações modifiquem dados.

    Com controles de simultaneidade pessimistas, as transações aplicam bloqueios nos documentos lidos. O bloqueio de uma transação em um documento impede que outras transações, gravações em lote e gravações não transacionais alterem o documento. Uma transação libera os bloqueios de documentos no momento da confirmação. Ela também libera os bloqueios quando eles expiram ou falham por algum motivo.

    Quando uma transação bloqueia um documento, outras operações de gravação precisam esperar que a transação remova o bloqueio. As transações adquirem os bloqueios em ordem cronológica.

  • OPTIMISTIC: os controles de simultaneidade otimista presumem que a disputa de dados não é provável ou que não é eficiente manter bloqueios do banco de dados. As transações otimistas não usam bloqueios de banco de dados para impedir que outras operações mudem dados.

    Com controles de simultaneidade otimistas, uma transação monitora todos os documentos lidos dentro dela. A transação concluirá as operações de gravação somente se nenhum desses documentos for alterado durante a execução da transação. Se algum documento tiver sido alterado, o gerenciador de transações repetirá a transação. Se não for possível conseguir o resultado desejado após algumas tentativas, a transação falhará devido à disputa de dados.

Padrões do modo de simultaneidade

O padrão para a edição Standard é PESSIMISTIC. O padrão para a edição Enterprise é OPTIMISTIC. No entanto, o comportamento também depende do tipo de biblioteca de cliente:

  • Os SDKs para dispositivos móveis/Web usam controles de simultaneidade otimistas. Os SDKs para dispositivos móveis e Web funcionam de maneira independente dessa configuração, já que sempre emulam simultaneidade otimista.

  • As bibliotecas de cliente do servidor usam controles de simultaneidade da configuração do banco de dados.

Disputa de dados nos SDKs para dispositivos móveis/Web

Os SDKs para dispositivos móveis e Web emulam transações de simultaneidade otimista usando pré-condições de gravação em versões de documentos. Essa emulação ocorre independente da configuração do modo de simultaneidade do banco de dados. Os SDKs para dispositivos móveis e Web não usam o recurso de transações integradas. Portanto, mesmo que o modo de simultaneidade do banco de dados esteja configurado para PESSIMISTIC, os clientes móveis ainda se comportam de maneira otimista.

Os SDKs para dispositivos móveis/Web usam controles de simultaneidade otimistas porque podem operar em ambientes com alta latência e uma conexão de rede não confiável. O bloqueio de documentos em um ambiente de alta latência causaria muitas falhas de disputa de dados.

Disputa de dados nas bibliotecas de cliente do servidor

As bibliotecas de cliente do servidor (C#, Go, Java, Node.js, PHP, Python, Ruby) usam o recurso de transações integradas. Essas transações usam a configuração do modo de simultaneidade no nível do banco de dados, e o padrão depende da edição:

  • A edição Enterprise usa controles de simultaneidade otimistas por padrão para oferecer suporte a operações que verificam coleções inteiras. Os controles de simultaneidade otimista ajudam a evitar operações de verificação que bloqueiam um grande número de documentos.

  • A edição Standard usa controles de simultaneidade pessimistas e pressupõe baixa latência e uma conexão confiável com o banco de dados.

Isolamento serializável

A disputa de dados entre transações está intimamente relacionada aos níveis de isolamento do banco de dados. O nível de isolamento de um banco de dados descreve como o sistema gerencia conflitos entre operações simultâneas. Os conflitos podem vir dos seguintes requisitos de banco de dados:

  • As transações exigem dados precisos e consistentes.
  • Para usar recursos com eficiência, os bancos de dados executam operações ao mesmo tempo.

Em sistemas com baixo nível de isolamento, uma operação de leitura em uma transação pode ler dados imprecisos de alterações não confirmadas em uma operação simultânea.

O isolamento serializável define o maior nível de isolamento. Isolamento serializado significa que:

  • você pode presumir que o banco de dados executa transações em série;
  • as transações não são afetadas por alterações não confirmadas em operações simultâneas.

Essa garantia precisa ser mantida mesmo quando o banco de dados executa várias transações em paralelo. O banco de dados precisa implementar controles de simultaneidade para resolver conflitos que violam essa garantia.

O Cloud Firestore garante o isolamento serializável de transações. As transações no Cloud Firestore são serializadas e isoladas por tempo de confirmação.

Isolamento serializável por tempo de confirmação

O Cloud Firestore atribui a cada transação um tempo de confirmação que representa um único ponto no tempo. Quando o Cloud Firestore confirma as alterações de uma transação no banco de dados, supõe-se que todas as leituras e gravações da transação ocorram exatamente no momento da confirmação.

A execução real de uma transação leva tempo. A execução de uma transação começa antes do tempo de confirmação, e a execução de várias operações pode se sobrepor. O Cloud Firestore mantém o isolamento serializável e garante que:

  • O Cloud Firestore confirma transações por ordem de tempo de confirmação.
  • O Cloud Firestore isola transações de operações simultâneas com um tempo de confirmação posterior.

No caso de disputa de dados entre operações simultâneas, o Cloud Firestore usa controles de simultaneidade otimistas e pessimistas para resolver a contenção.

Isolamento dentro de uma transação

O isolamento da transação também se aplica a operações de gravação dentro dela. As consultas e leituras dentro de uma transação não veem os resultados das gravações anteriores dentro dessa transação. Mesmo que você modifique ou exclua um documento dentro de uma transação, todas as leituras de documentos dessa transação retornarão a versão do documento no momento da confirmação, antes das operações de gravação. Se naquele momento o documento não existia, as operações de leitura não retornam nada.

Problemas com contenção de dados

Para mais informações sobre contenção de dados e como resolver isso, confira a página de solução de problemas.