Nesta página, descrevemos as transações no Spanner e apresentamos as interfaces de transação de leitura e gravação, somente leitura e DML particionada do Spanner.
Uma transação no Spanner é um conjunto de leituras e gravações executadas atomicamente em um único ponto lógico no tempo entre colunas, linhas e tabelas de um banco de dados.
Uma sessão é usada para realizar transações em um banco de dados do Spanner. Uma sessão representa um canal de comunicação lógico com o serviço de banco de dados do Spanner. As sessões podem executar uma ou várias transações por vez. Para mais informações, consulte Sessões.
Tipos de transação
O Spanner é compatível com os seguintes tipos de transação, cada um projetado para padrões específicos de interação de dados:
Leitura e gravação:essas transações usam bloqueio pessimista e, se necessário, um commit de duas fases. Elas podem falhar e exigir novas tentativas. Embora estejam confinados a um único banco de dados, eles podem modificar dados em várias tabelas dentro desse banco de dados.
Somente leitura:essas transações garantem a consistência dos dados em várias operações de leitura, mas não permitem modificações. Eles são executados em um carimbo de data/hora determinado pelo sistema para consistência ou em um carimbo de data/hora passado configurado pelo usuário. Ao contrário das transações de leitura e gravação, elas não exigem uma operação de confirmação ou bloqueios, embora possam pausar para aguardar a conclusão das operações de gravação em andamento.
DML particionada:esse tipo de transação executa instruções DML como operações de DML particionada. Ele é otimizado para atualizações e exclusões de dados em grande escala, como limpeza ou inserção em massa de dados. Para várias gravações que não precisam de uma transação atômica, use gravações em lote. Consulte Modificar dados usando gravações em lote para mais detalhes.
Transações de leitura e gravação
Use transações de leitura e gravação de bloqueio para ler, modificar e gravar dados de maneira atômica em qualquer lugar de um banco de dados. Esse tipo de transação é consistente externamente.
Minimizar o tempo em que uma transação fica ativa. Transações mais curtas aumentam a probabilidade de um commit bem-sucedido e reduzem a disputa.
O Spanner tenta manter os bloqueios de leitura ativos enquanto a transação continua realizando leituras e não é encerrada por operações sessions.commit
ou sessions.rollback
.
Se o cliente ficar inativo por longos períodos, o Spanner poderá liberar os bloqueios da transação e interrompê-la.
Conceitualmente, uma transação de leitura/gravação consiste em zero ou mais leituras ou instruções SQL seguidas por sessions.commit
. A qualquer momento antes de sessions.commit
,
o cliente pode enviar uma solicitação sessions.rollback
para anular a transação.
Para realizar uma operação de gravação que depende de uma ou mais operações de leitura, use uma transação de leitura e gravação com bloqueio:
- Se você precisar confirmar uma ou mais operações de gravação de forma atômica, faça essas gravações na mesma transação de leitura e gravação. Por exemplo, se você transferir US$ 200 da conta A para a conta B, execute as duas operações de gravação (diminuindo US $200 da conta A e aumentando US $200 da conta B) e as leituras dos saldos iniciais das contas na mesma transação.
- Se você quiser dobrar o saldo da conta A, faça as operações de leitura e gravação na mesma transação. Isso garante que o sistema leia o saldo antes de dobrá-lo e atualizá-lo.
- Se você puder realizar uma ou mais operações de gravação que dependam dos resultados de uma ou mais operações de leitura, faça essas gravações e leituras na mesma transação de leitura e gravação, mesmo que as operações de gravação não sejam executadas. Por exemplo, se você quiser transferir US $200 da conta A para a conta B somente se o saldo atual de A for superior a US $500, inclua a leitura do saldo de A e as operações de gravação 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 somente leitura:
- Se você estiver apenas realizando operações de leitura e puder expressar a operação usando um método de leitura única, use esse método ou uma transação somente leitura. Ao contrário das transações de leitura e gravação, as leituras únicas não adquirem bloqueios.
Interface
As bibliotecas de cliente do Spanner fornecem uma interface para executar um conjunto de trabalho em uma transação de leitura e gravação, com novas tentativas de cancelamento de transação. Uma transação do Spanner pode exigir várias novas tentativas antes de ser confirmada.
Várias situações podem causar a interrupção de transações. Por exemplo, se duas transações tentarem modificar dados simultaneamente, poderá ocorrer um impasse. Nesses casos, o Spanner cancela uma transação para permitir que a outra continue. Com menos frequência, eventos temporários no Spanner também podem causar cancelamentos de transações.
Como as transações são atômicas, uma transação cancelada não afeta o banco de dados. Tente de novo na mesma sessão para melhorar as taxas de sucesso. Cada nova tentativa que resulta em um erro ABORTED
aumenta a prioridade de bloqueio da transação.
Ao usar uma transação em uma biblioteca de cliente do Spanner, você define o corpo da transação como um objeto de função. Essa função encapsula as leituras e gravações realizadas em uma ou mais tabelas de banco de dados. A biblioteca de cliente do Spanner executa essa função repetidamente até que a transação seja confirmada ou encontre um erro que não possa ser repetido.
Exemplo
Suponha que você tenha 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 departamento de marketing pede para você transferir US $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. Use uma transação de leitura e gravação com bloqueio para essa operação porque, dependendo do resultado de uma leitura, é possível que a transação faça alguma gravação.
Veja a seguir como executar uma transação de leitura e gravação:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Semântica
Esta seção descreve a semântica das transações de leitura e gravação no Spanner.
Propriedades
Uma transação de leitura e gravação no Spanner executa um conjunto de leituras e gravações atomicamente. O carimbo de data/hora em que as transações de leitura e gravação são executadas corresponde ao tempo decorrido. A ordem de serialização corresponde à ordem do carimbo de data/hora.
As transações de leitura e gravação oferecem as propriedades ACID dos bancos de dados relacionais. As transações de leitura e gravação do Spanner oferecem propriedades mais fortes do que o ACID típico.
Devido a essas propriedades, como desenvolvedor de aplicativos, você se concentra na exatidão de cada transação por si só, sem se preocupar em como proteger a execução dela contra outras transações que podem ser executadas ao mesmo tempo.
Isolamento para transações de leitura e gravação
Depois de confirmar uma transação que contém uma série de leituras e gravações, você verá o seguinte:
- A transação retorna valores que refletem um snapshot consistente no carimbo de data/hora de confirmação da transação.
- Linhas ou intervalos vazios permanecem vazios no momento do commit.
- A transação confirma todas as gravações no carimbo de data/hora de confirmação da transação.
- Nenhuma transação pode ver as gravações até que a transação seja confirmada.
Os drivers de cliente do Spanner incluem uma lógica de novas tentativas de transação que mascara erros transitórios ao executar novamente a transação e validar os dados que o cliente observa.
O efeito é que todas as leituras e gravações parecem ter ocorrido em um único momento, tanto da perspectiva da própria transação quanto da perspectiva de outros leitores e gravadores no banco de dados do Spanner. Isso significa que as leituras e gravações ocorrem no mesmo carimbo de data/hora. Para ver um exemplo, consulte Capacidade de serialização e consistência externa.
Isolamento para transações de leitura
Quando uma transação de leitura e gravação executa apenas operações de leitura, ela oferece garantias de consistência semelhantes a uma transação somente leitura. Todas as leituras dentro da transação retornam dados de um carimbo de data/hora consistente, incluindo a confirmação de linhas inexistentes.
Uma diferença é quando uma transação de leitura e gravação é confirmada sem executar uma operação de gravação. Nesse cenário, não há garantia de que os dados lidos na transação permaneceram inalterados no banco de dados entre a operação de leitura e a confirmação da transação.
Para garantir a atualização dos dados e validar que eles não foram modificados desde a última recuperação, é necessária uma leitura subsequente. Essa releitura pode ser realizada em outra transação de leitura e gravação ou com uma leitura consistente.
Para otimizar a eficiência, se uma transação estiver realizando apenas leituras, use uma transação somente leitura em vez de uma transação de leitura/gravação.
Atomicidade, consistência, durabilidade
Além do isolamento, o Spanner oferece as outras garantias de propriedades ACID:
- Atomicidade. Uma transação é considerada atômica se todas as operações forem concluídas com sucesso ou nenhuma delas. Se alguma operação em uma transação falhar, toda a transação será revertida ao estado original, garantindo a integridade dos dados.
- Consistência. Uma transação precisa manter a integridade das regras e restrições do banco de dados. Depois que uma transação é concluída, o banco de dados precisa estar em um estado válido, obedecendo a regras predefinidas.
- Durabilidade. Depois que uma transação é confirmada, as mudanças são armazenadas permanentemente no banco de dados e persistem em caso de falhas no sistema, quedas de energia ou outras interrupções.
Capacidade de serialização e consistência externa
O Spanner oferece garantias transacionais fortes, incluindo capacidade de serialização e consistência externa. Essas propriedades garantem que os dados permaneçam consistentes e que as operações ocorram em uma ordem previsível, mesmo em um ambiente distribuído.
A capacidade de serialização garante que todas as transações pareçam ser executadas uma após a outra em uma única ordem sequencial, mesmo que sejam processadas simultaneamente. O Spanner faz isso atribuindo carimbos de data/hora de confirmação às transações, refletindo a ordem em que elas foram confirmadas.
O Spanner oferece uma garantia ainda mais forte, conhecida como consistência externa. Isso significa que não apenas as transações são confirmadas em uma ordem refletida pelos carimbos de data/hora de confirmação, mas esses carimbos também se alinham ao tempo real. Isso permite comparar carimbos de data/hora de confirmação com o tempo real, fornecendo uma visualização consistente e globalmente ordenada dos seus dados.
Em essência, se uma transação Txn1
for confirmada antes de outra transação Txn2
em tempo real, o carimbo de data/hora de confirmação de Txn1
será anterior ao carimbo de data/hora de confirmação de Txn2
.
Veja o exemplo a seguir.
Nesse cenário, durante o período t
:
- A transação
Txn1
lê os dadosA
, prepara uma gravação emA
e, em seguida, faz a confirmação. - A transação
Txn2
começa depois queTxn1
é iniciada. Ele lê os dadosB
e depois os dadosA
.
Mesmo que Txn2
tenha começado antes da conclusão de Txn1, Txn2
observa as mudanças feitas por Txn1
em A
. Isso ocorre porque Txn2
lê A
depois que Txn1
confirma
a gravação em A
.
Embora Txn1
e Txn2
possam se sobrepor no tempo de execução, os carimbos de data/hora de confirmação, c1
e c2
, respectivamente, impõem uma ordem linear de transação. Isso
significa:
- Todas as leituras e gravações em
Txn1
parecem ter ocorrido em um único ponto no tempo,c1
. - Todas as leituras e gravações em
Txn2
parecem ter ocorrido em um único ponto no tempo,c2
. - É importante notar que
c1
é anterior ac2
para gravações confirmadas, mesmo que elas tenham ocorrido em máquinas diferentes. SeTxn2
realizar apenas leituras,c1
será anterior ou igual ac2
.
Essa ordenação forte significa que, se uma operação de leitura subsequente observar os efeitos de Txn2
, ela também vai observar os efeitos de Txn1
. Essa propriedade é verdadeira para todas as transações confirmadas com sucesso.
Garantias de leitura e gravação em caso de falha na transação
Se uma chamada para executar uma transação falhar, as garantias de leitura e gravação dependerão do erro com que a chamada de confirmação subjacente falhou.
Por exemplo, um erro como "Linha não encontrada" ou "Linha já existe" indica que a gravação das mutações armazenadas em buffer encontrou algum erro, por exemplo: uma linha que o cliente está tentando atualizar não existe. Nesse caso, as leituras são garantidas de maneira consistente, as gravações não são aplicadas e a inexistência da linha é garantida para também ser consistente com as leituras.
Garantias de leitura e gravação em caso de falha na transação
Quando uma transação do Spanner falha, as garantias que você recebe para
leituras e gravações dependem do erro específico encontrado durante a operação commit
.
Por exemplo, uma mensagem de erro como "Linha não encontrada" ou "Linha já existe" indica um problema durante a gravação de mutações armazenadas em buffer. Isso pode acontecer se, por exemplo, uma linha que o cliente está tentando atualizar não existir. Nesses cenários:
- As leituras são consistentes:todos os dados lidos durante a transação têm garantia de consistência até o ponto do erro.
- As gravações não são aplicadas:as mutações que a transação tentou não são confirmadas no banco de dados.
- Consistência de linha:a não existência (ou estado existente) da linha que acionou o erro é consistente com as leituras realizadas na transação.
É possível cancelar operações de leitura assíncronas no Spanner a qualquer momento sem afetar outras operações em andamento na mesma transação. Essa flexibilidade é útil se uma operação de nível superior for cancelada ou se você decidir interromper uma leitura com base nos resultados iniciais.
No entanto, é importante entender que solicitar o cancelamento de uma leitura não garante a rescisão imediata. Depois de um pedido de cancelamento, a operação de leitura ainda pode:
- Concluída com sucesso:a leitura pode terminar o processamento e retornar resultados antes que o cancelamento entre em vigor.
- Falha por outro motivo:a leitura pode ser encerrada devido a um erro diferente, como uma anulação.
- Retornar resultados incompletos:a leitura pode retornar resultados parciais, que são validados como parte do processo de confirmação da transação.
Também vale a pena observar a distinção com as operações de transação commit
: o cancelamento de um commit
anula toda a transação, a menos que ela já tenha sido confirmada ou falhado por outro motivo.
Desempenho
Esta seção descreve problemas que afetam o desempenho das transações de leitura e gravação.
Controle de simultaneidade de bloqueio
O Spanner permite que vários clientes interajam com o mesmo banco de dados simultaneamente. Para manter a consistência dos dados nessas transações simultâneas, o Spanner tem um mecanismo de bloqueio que usa bloqueios compartilhados e exclusivos.
Quando uma transação executa uma operação de leitura, o Spanner adquire bloqueios compartilhados de leitura nos dados relevantes. Esses bloqueios compartilhados permitem que outras operações de leitura simultâneas acessem os mesmos dados. Essa simultaneidade é mantida até que sua transação se prepare para confirmar as mudanças.
Durante a fase de confirmação, à medida que as gravações são aplicadas, a transação tenta fazer upgrade dos bloqueios para bloqueios exclusivos. Para isso, ele faz o seguinte:
- Bloqueia novas solicitações de bloqueio compartilhado de leitura nos dados afetados.
- Aguarde a liberação de todos os bloqueios compartilhados de leitura nos dados.
- Depois que todos os bloqueios compartilhados de leitura são limpos, ele coloca um bloqueio exclusivo, concedendo acesso único aos dados durante a gravação.
Observações sobre bloqueios:
- Granularidade:o Spanner aplica bloqueios na granularidade de linha e coluna. Isso significa que, se a transação
T1
tiver um bloqueio na colunaA
da linhaalbumid
, a transaçãoT2
ainda poderá gravar simultaneamente na colunaB
da mesma linhaalbumid
sem conflito. - Gravações sem leituras:para gravações sem leituras, o Spanner não exige um bloqueio exclusivo. Em vez disso, ele usa um bloqueio compartilhado de gravação. Isso ocorre porque a ordem de aplicação para gravações sem leituras é determinada pelos carimbos de data/hora de confirmação, permitindo que vários gravadores operem no mesmo item simultaneamente sem conflito. Um bloqueio exclusivo só é necessário se a transação primeiro ler os dados que pretende gravar.
- Índices secundários para pesquisas de linhas:ao realizar pesquisas de linhas em uma transação de leitura e gravação, o uso de índices secundários pode melhorar significativamente o desempenho. Ao usar índices secundários para limitar as linhas verificadas a um intervalo menor, o Spanner bloqueia menos linhas na tabela, permitindo uma maior modificação simultânea de linhas fora desse intervalo específico.
- Acesso exclusivo a recursos externos:os bloqueios internos do Spanner são projetados para consistência de dados no próprio banco de dados do Spanner. Não os use para garantir acesso exclusivo a recursos fora do Spanner. O Spanner pode cancelar transações por vários motivos, incluindo otimizações internas do sistema como movimentação de dados entre recursos de computação. Se uma transação for repetida (explicitamente pelo código do aplicativo ou implicitamente por bibliotecas de cliente, como o driver JDBC do Spanner), os bloqueios só serão mantidos durante a tentativa de confirmação bem-sucedida.
- Estatísticas de bloqueio:para diagnosticar e investigar conflitos de bloqueio no seu banco de dados, use a ferramenta de introspecção Estatísticas de bloqueio.
Detecção de impasses
O Spanner detecta quando várias transações podem estar bloqueadas
e obriga o cancelamento de todas as transações, exceto uma. Considere este cenário: Txn1
mantém um bloqueio no registro A
e está aguardando um bloqueio no registro B
, enquanto Txn2
mantém um bloqueio no registro B
e está aguardando um bloqueio no registro A
. Para
resolver isso, uma das transações precisa ser cancelada, liberando o bloqueio e
permitindo que a outra continue.
O Spanner usa o algoritmo padrão wound-wait para detecção de impasse. Em segundo plano, o Spanner acompanha a idade de cada transação que solicita bloqueios conflitantes. Ele permite que transações mais antigas anulem as mais recentes. Uma transação mais antiga é aquela cuja primeira leitura, consulta ou confirmação ocorreu antes.
Ao priorizar transações mais antigas, o Spanner garante que todas as transações vão adquirir bloqueios com o tempo, depois que tiverem idade suficiente para ter prioridade mais alta. Por exemplo, uma transação mais antiga que precisa de um bloqueio compartilhado de gravador pode interromper uma transação mais recente que tenha um bloqueio compartilhado de leitor.
Execução distribuída
O Spanner pode executar transações em dados que abrangem vários servidores, mas essa capacidade tem um custo de desempenho em comparação com transações de servidor único.
Quais tipos de transações podem ser distribuídos? O Spanner pode distribuir a responsabilidade por linhas do banco de dados entre vários servidores. Normalmente, uma linha e as linhas correspondentes da tabela intercalada são disponibilizadas pelo mesmo servidor, assim como duas linhas na mesma tabela com chaves próximas. O Spanner pode executar transações em linhas em diferentes servidores. No entanto, como regra geral, as transações que afetam muitas linhas colocalizadas são mais rápidas e baratas do que aquelas que afetam muitas linhas espalhadas por todo o banco de dados ou uma tabela grande.
As transações mais eficientes no Spanner incluem somente as leituras e gravações que precisam ser aplicadas atomicamente. As transações são mais rápidas quando todas as leituras e gravações acessam dados na mesma parte do espaço de chave.
Transações somente leitura
Além de bloquear transações de leitura e gravação, o Spanner oferece transações somente leitura.
Use uma transação somente leitura quando precisar executar mais de uma leitura no mesmo carimbo de data/hora. Se você puder expressar sua leitura usando um dos métodos de leitura única do Spanner, use esse método. O desempenho da utilização de uma chamada de leitura única é comparável ao de uma única leitura feita em uma transação somente leitura.
Se você estiver lendo uma grande quantidade de dados, use partições para ler os dados em paralelo.
Como as transações somente leitura não gravam, elas não mantêm bloqueios e não bloqueiam outras transações. As transações somente leitura estão de acordo com um prefixo consistente do histórico de confirmações da transação. Portanto, o aplicativo sempre recebe dados consistentes.
Interface
O Spanner oferece uma interface para executar um conjunto de trabalho no contexto de uma transação somente leitura, com novas tentativas para cancelamentos de transações.
Exemplo
O exemplo a seguir mostra como usar uma transação somente leitura para receber dados consistentes para duas leituras no mesmo carimbo de data/hora:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Semântica
Esta seção descreve a semântica das transações somente leitura.
Transações somente leitura de snapshots
Quando uma transação somente leitura é executada no Spanner, ela realiza todas as leituras em um único ponto lógico no tempo. Isso significa que a transação somente leitura e qualquer outro leitor e gravador simultâneo veem um instantâneo consistente do banco de dados naquele momento específico.
Essas transações somente leitura de snapshot oferecem uma abordagem mais simples para leituras consistentes em comparação com o bloqueio de transações de leitura/gravação. Geralmente, estes são os motivos:
- Sem bloqueios:as transações somente leitura não adquirem bloqueios. Em vez disso, elas selecionam um carimbo de data/hora do Spanner e executam todas as leituras na versão histórica dos dados. Como elas não usam bloqueios, não bloqueiam transações simultâneas de leitura e gravação.
- Nenhum encerramento:essas transações nunca são encerradas. Embora possam falhar se o carimbo de data/hora de leitura escolhido for coletado como lixo, a política padrão de coleta de lixo do Spanner geralmente é generosa o suficiente para que a maioria dos aplicativos não encontre esse problema.
- Sem commits ou rollbacks:as transações somente leitura não exigem chamadas para
sessions.commit
ousessions.rollback
e são impedidas de fazer isso.
Para executar uma transação de snapshot, o cliente define um limite de carimbo de data/hora, que instrui o Spanner a selecionar um carimbo de data/hora de leitura. Os tipos de limites de carimbo de data/hora incluem:
- Leituras fortes:garantem que você veja os efeitos de todas as transações confirmadas antes do início da leitura. Todas as linhas em uma única leitura são consistentes. No entanto, as leituras consistentes não são repetíveis, embora elas retornem um carimbo de data/hora, e a leitura novamente nesse mesmo carimbo seja repetível. Duas transações fortes somente leitura consecutivas podem produzir resultados diferentes devido a gravações simultâneas. As consultas em fluxo de alterações precisam usar esse limite. Para mais detalhes, consulte TransactionOptions.ReadOnly.strong.
- Desatualização exata:essa opção executa leituras em um carimbo de data/hora especificado, seja como um carimbo de data/hora absoluto ou como uma duração de desatualização relativa ao horário atual. Ele garante que você observe um prefixo consistente do histórico de transações globais até esse carimbo de data/hora e bloqueia transações conflitantes que possam ser confirmadas com um carimbo de data/hora menor ou igual ao carimbo de data/hora de leitura. Embora seja um pouco mais rápido que os modos de defasagem limitada, ele pode retornar dados mais antigos. Para mais detalhes, consulte TransactionOptions.ReadOnly.read_timestamp e TransactionOptions.ReadOnly.exact_staleness.
- Inatividade limitada:o Spanner seleciona o carimbo de data/hora mais recente dentro de um limite de inatividade definido pelo usuário, permitindo a execução na réplica disponível mais próxima sem bloqueio. Todas as linhas retornadas são consistentes. Assim como as leituras consistentes, a inatividade limitada não é repetível, já que leituras diferentes podem ser executadas com carimbos de data/hora diferentes, mesmo com o mesmo limite. Essas leituras operam em duas fases (negociação de carimbo de data/hora e leitura) e geralmente são um pouco mais lentas do que a inatividade exata, mas costumam retornar resultados mais recentes e têm mais chances de serem executadas em uma réplica local. Esse modo só está disponível para transações somente leitura de uso único porque a negociação de carimbo de data/hora exige saber quais linhas serão lidas com antecedência. Para mais detalhes, consulte TransactionOptions.ReadOnly.max_staleness e TransactionOptions.ReadOnly.min_read_timestamp.
Transações de DML particionada
É possível usar a DML particionada para executar instruções UPDATE
e DELETE
em larga escala sem encontrar limites de transação ou bloquear uma tabela inteira. O Spanner faz isso particionando o espaço de chaves e executando as instruções DML em cada partição em uma transação de leitura e gravação separada.
Para usar DML não particionada, execute instruções em transações de leitura e gravação que você cria explicitamente no código. Para mais detalhes, consulte Como usar a DML.
Interface
O Spanner fornece a interface TransactionOptions.partitionedDml para executar uma única instrução DML particionada.
Exemplos
O exemplo de código a seguir atualiza a coluna MarketingBudget
da tabela Albums
.
C++
Use a função ExecutePartitionedDml()
para executar uma instrução DML particionada.
C#
Use o método ExecutePartitionedUpdateAsync()
para executar uma instrução DML particionada.
Go
Use o método PartitionedUpdate()
para executar uma instrução DML particionada.
Java
Use o método executePartitionedUpdate()
para executar uma instrução DML particionada.
Node.js
Use o método runPartitionedUpdate()
para executar uma instrução DML particionada.
PHP
Use o método executePartitionedUpdate()
para executar uma instrução DML particionada.
Python
Use o método execute_partitioned_dml()
para executar uma instrução DML particionada.
Ruby
Use o método execute_partitioned_update()
para executar uma instrução DML particionada.
O exemplo de código a seguir exclui linhas da tabela Singers
com base na coluna SingerId
.
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Semântica
Esta seção descreve a semântica da DML particionada.
Noções básicas sobre a execução da DML particionada
É possível executar apenas uma instrução DML particionada por vez, seja usando um método de biblioteca de cliente ou a Google Cloud CLI.
As transações particionadas não são compatíveis com confirmações ou rollbacks. O Spanner executa e aplica a instrução DML imediatamente. Se você cancelar a operação ou ela falhar, o Spanner vai cancelar todas as partições em execução e não vai iniciar as restantes. No entanto, o Spanner não reverter partições que já foram executadas.
Estratégia de aquisição de bloqueio da DML particionada
Para reduzir a disputa por bloqueio, a DML particionada adquire bloqueios de leitura apenas nas linhas que correspondem à cláusula WHERE
. Transações menores e independentes usadas para cada partição também mantêm bloqueios por menos tempo.
Limites de transação da sessão
Cada sessão no Spanner pode ter uma transação ativa por vez. Isso inclui leituras e consultas independentes, que usam uma transação internamente e contam para esse limite. Depois que uma transação é concluída, a sessão pode ser reutilizada imediatamente para a próxima transação. Não é necessário criar uma nova sessão para cada transação.
Carimbos de data/hora de leitura antigos e coleta de lixo de versões
O Spanner realiza a coleta de lixo de versões para coletar dados excluídos ou
substituídos e recuperar armazenamento. Por padrão, os dados com mais de uma hora são
recuperados. O Spanner não pode executar leituras em carimbos de data/hora mais antigos que o VERSION_RETENTION_PERIOD
configurado, que é de uma hora por padrão, mas pode ser configurado para até uma semana. Quando as leituras ficam muito antigas durante a execução, elas falham e retornam o erro FAILED_PRECONDITION
.
Consultas em fluxo de alterações
Um fluxo de alterações é um objeto de esquema que pode ser configurado para monitorar modificações de dados em um banco de dados inteiro, em tabelas específicas ou em um conjunto definido de colunas em um banco de dados.
Quando você cria um fluxo de alterações, o Spanner define uma função de valor de tabela (TVF) do SQL correspondente. É possível usar essa TVF para consultar os registros de mudança no fluxo de alterações associado com o método sessions.executeStreamingSql
. O nome da TVF é gerado com base no nome do fluxo de alterações e sempre começa com READ_
.
Todas as consultas em TVFs de fluxo de alterações precisam ser executadas usando a
API sessions.executeStreamingSql
em uma transação somente leitura de uso único
com um timestamp_bound
somente leitura forte. Com a TVF de fluxo de alterações, é possível especificar start_timestamp
e end_timestamp
para o período. Todos os registros de
mudança dentro do período de armazenamento podem ser acessados usando o timestamp_bound
somente leitura
forte. Todos os outros TransactionOptions
são inválidos para consultas de fluxo de mudanças.
Além disso, se
TransactionOptions.read_only.return_read_timestamp
estiver definido como true
, a
mensagem Transaction
que descreve
a transação vai retornar um valor especial de 2^63 - 2
em vez de um carimbo de data/hora de leitura
válido. Descarte esse valor especial e não o use em consultas subsequentes.
Para mais informações, consulte Fluxo de trabalho de consulta de streams de alterações.
Transações inativas
Uma transação é considerada inativa se não tiver leituras ou consultas SQL pendentes e não tiver iniciado uma nos últimos 10 segundos. O Spanner pode anular transações
inativas para evitar que elas mantenham bloqueios indefinidamente. Se uma transação
inativa for anulada, a confirmação vai falhar e retornar um erro ABORTED
.
Executar periodicamente uma pequena consulta, como SELECT 1
, na transação pode evitar que ela fique inativa.