Esta página descreve as transações no Spanner e apresenta as interfaces de transação DML de leitura/escrita, só de leitura e particionadas do Spanner.
Uma transação no Spanner é um conjunto de leituras e escritas. Todas as operações numa transação são atómicas, o que significa que têm todas êxito ou todas falham.
Uma sessão é usada para realizar transações numa base de dados do Spanner. Uma sessão representa um canal de comunicação lógico com o serviço de base de dados do Spanner. As sessões podem executar uma ou várias transações de cada vez. Para mais informações, consulte o artigo Sessões.
Tipos de transações
O Spanner suporta os seguintes tipos de transações, cada um concebido para padrões de interação de dados específicos:
Leitura/escrita: estas transações são usadas para operações de leitura e escrita, seguidas de uma confirmação. Podem adquirir fechaduras. Se falharem, vão precisar de novas tentativas. Embora estejam restritas a uma única base de dados, podem modificar dados em várias tabelas nessa base de dados.
Só de leitura: estas transações garantem a consistência dos dados em várias operações de leitura, mas não permitem modificações de dados. São executados numa data/hora determinada pelo sistema para garantir a consistência ou numa data/hora passada configurada pelo utilizador. Ao contrário das transações de leitura/escrita, não requerem uma operação de confirmação nem bloqueios. No entanto, podem ser pausadas para aguardar a conclusão das operações de escrita em curso.
DML particionada: este tipo de transação executa instruções DML como operações de DML particionada. Está otimizado para executar declarações DML em grande escala, mas com restrições para garantir que a declaração é idempotente e divisível de uma forma que lhe permita ser executada independentemente de outras partições. Para várias escritas que não precisam de uma transação atómica, considere usar escritas em lote. Para mais informações, consulte o artigo Modifique dados através de gravações em lote.
Transações de leitura/escrita
Uma transação de leitura/escrita consiste em zero ou mais leituras ou declarações de consulta seguidas de um pedido de confirmação. Em qualquer altura antes do pedido de confirmação, o cliente pode enviar um pedido de reversão para anular a transação.
Isolamento serializável
Usando o nível de isolamento serializável predefinido, as transações de leitura/escrita leem, modificam e escrevem dados de forma atómica. Este tipo de transação é externamente consistente.
Quando usa transações de leitura/escrita, recomendamos que minimize o tempo em que uma transação está ativa. As durações das transações mais curtas resultam em bloqueios mantidos durante menos tempo, o que aumenta a probabilidade de uma confirmação bem-sucedida e reduz a contenção. Isto deve-se ao facto de os bloqueios mantidos durante muito tempo poderem levar a bloqueios permanentes e anulações de transações. O Spanner tenta manter os bloqueios de leitura ativos enquanto a transação continuar a executar leituras e a transação não tiver terminado através de confirmação ou reversão. Se o cliente permanecer inativo durante longos períodos, o Spanner pode libertar os bloqueios da transação e anular a transação.
Para realizar uma operação de escrita que dependa de uma ou mais operações de leitura, use uma transação de leitura/escrita:
- Se tiver de confirmar uma ou mais operações de escrita de forma atómica, execute essas escritas na mesma transação de leitura/escrita. Por exemplo, se transferir 200 € da conta A para a conta B, execute ambas as operações de escrita (diminuindo a conta A em 200 € e aumentando a conta B em 200 €) e as leituras dos saldos iniciais das contas na mesma transação.
- Se quiser duplicar o saldo da conta A, execute as operações de leitura e escrita na mesma transação. Isto garante que o sistema lê o saldo antes de o duplicar e atualizar.
- Se as operações de escrita dependerem das operações de leitura, execute ambas na mesma transação de leitura/escrita, mesmo que as escritas não sejam executadas. Por exemplo, se quiser transferir 200 € da conta A para a conta B apenas se o saldo da conta A for superior a 500 €, inclua a leitura do saldo da conta A e as operações de escrita condicional na mesma transação, mesmo que a transferência não ocorra.
Para realizar operações de leitura, use um único método de leitura ou uma transação só de leitura:
- Se estiver a realizar apenas operações de leitura e puder expressar a operação de leitura através de um método de leitura único, use o método de leitura único ou uma transação só de leitura. Ao contrário das transações de leitura/escrita, as leituras únicas não adquirem bloqueios.
Isolamento de leitura repetível
No Spanner, o isolamento de leitura repetível é implementado através de uma técnica conhecida como isolamento de instantâneos. O isolamento de leitura repetível garante que todas as operações de leitura numa transação são consistentes com a base de dados tal como existia no início da transação. Também garante que as escritas simultâneas nos mesmos dados só têm êxito se não existirem conflitos.
Com o seu bloqueio otimista predefinido, não são adquiridos bloqueios até à hora de confirmação se for necessário escrever dados. Se existir um conflito com os dados escritos ou devido a eventos transitórios no Spanner, como um reinício do servidor, o Spanner pode continuar a anular transações. Uma vez que as leituras em transações de leitura/escrita não adquirem bloqueios no isolamento de leitura repetível, não existe diferença entre a execução de operações só de leitura numa transação só de leitura ou numa transação de leitura/escrita.
Considere usar transações de leitura/escrita no isolamento de leitura repetível nos seguintes cenários:
- A carga de trabalho é de leitura intensiva e tem poucos conflitos de escrita.
- A aplicação está a sofrer restrições de desempenho devido a atrasos na contenção de bloqueios e a anulações de transações causadas por transações mais antigas e de prioridade superior que prejudicam transações mais recentes e de prioridade inferior para evitar potenciais bloqueios mútuos (wound-wait).
- A aplicação não requer as garantias mais rigorosas fornecidas pelo nível de isolamento serializável.
Quando realiza uma operação de escrita que depende de uma ou mais operações de leitura, é possível ocorrer uma distorção de escrita no isolamento de leitura repetível. A distorção de escrita surge de um tipo específico de atualização concorrente, em que cada atualização é aceite de forma independente, mas o respetivo efeito combinado viola a integridade dos dados da aplicação.
Por conseguinte, certifique-se de que executa leituras que fazem parte da secção crítica de uma transação com uma cláusula FOR UPDATE ou uma sugestão lock_scanned_ranges=exclusive para evitar a distorção de escrita. Para mais informações, consulte os artigos
Conflitos de leitura/escrita e correção
e o exemplo abordado em
Semântica de leitura/escrita.
Interface
As bibliotecas cliente do Spanner fornecem uma interface para executar um conjunto de tarefas numa transação de leitura/escrita com novas tentativas para anulações de transações. Uma transação pode exigir várias novas tentativas antes de ser confirmada.
Várias situações podem causar a anulação de transações. Por exemplo, se duas transações tentarem modificar dados em simultâneo, pode ocorrer um impasse. Nestes casos, o Spanner anula uma transação para permitir que a outra continue. Com menos frequência, os eventos transitórios no Spanner também podem causar a anulação de transações.
Todas as transações de leitura/escrita oferecem as propriedades ACID das bases de dados relacionais.
Uma vez que as transações são atómicas, uma transação anulada não afeta a base de dados. As bibliotecas de cliente do Spanner repetem automaticamente essas transações, mas se não usar as bibliotecas de cliente, repita a transação na mesma sessão para melhorar as taxas de êxito. Cada nova tentativa que resulte num erro ABORTED aumenta a prioridade de bloqueio da transação. Além disso, os controladores do cliente do Spanner incluem uma lógica de repetição de transações interna que oculta erros temporários ao executar novamente a transação.
Quando usa uma transação numa biblioteca de cliente do Spanner, define o corpo da transação como um objeto de função. Esta função encapsula as leituras e as escritas realizadas numa ou mais tabelas de base de dados. A biblioteca de cliente do Spanner executa esta função repetidamente até que a transação seja confirmada com êxito ou encontre um erro que não possa ser repetido.
Exemplo
Suponhamos que tem uma coluna MarketingBudget na tabela Albums:
CREATE TABLE Albums ( SingerId INT64 NOT NULL, AlbumId INT64 NOT NULL, AlbumTitle STRING(MAX), MarketingBudget INT64 ) PRIMARY KEY (SingerId, AlbumId);
O seu departamento de marketing pede-lhe para transferir 200 000 € do orçamento de Albums
(2, 2) para Albums (1, 1), mas apenas se o dinheiro estiver disponível no orçamento desse álbum. Deve usar uma transação de leitura/escrita de bloqueio para esta operação, uma vez que a transação pode realizar escritas consoante o resultado de uma leitura.
Os exemplos da biblioteca de cliente seguintes mostram como executar uma transação de leitura/escrita usando o nível de isolamento serializável predefinido: