Transações e controlo de simultaneidade otimista

APLICA-SE A: NoSQL

As transações de banco de dados fornecem um modelo de programação seguro e previsível para lidar com alterações simultâneas nos dados. Os bancos de dados relacionais tradicionais, como o SQL Server, permitem que você escreva a lógica de negócios usando procedimentos armazenados e/ou gatilhos, envie-a para o servidor para execução diretamente no mecanismo de banco de dados. Com bancos de dados relacionais tradicionais, você é obrigado a lidar com duas linguagens de programação diferentes: a linguagem de programação de aplicativos (não transacionais), como JavaScript, Python, C#, Java, etc., e a linguagem de programação transacional (como T-SQL) que é executada nativamente pelo banco de dados.

O mecanismo de banco de dados no Azure Cosmos DB dá suporte a transações completas compatíveis com ACID (Atomicidade, Consistência, Isolamento, Durabilidade) com isolamento de instantâneo. Todas as operações de banco de dados dentro do escopo da partição lógica de um contêiner são executadas transacionalmente dentro do mecanismo de banco de dados hospedado pela réplica da partição. Essas operações incluem operações de gravação (atualização de um ou mais itens dentro da partição lógica) e de leitura. A tabela a seguir ilustra diferentes operações e tipos de transação:

Operação Tipo de Operação Transação de item único ou múltiplo
Inserir (sem um gatilho pré/pós) Escrita Transação de item único
Inserir (com um gatilho pré/pós) Escrever e Ler Transação com vários itens
Substituir (sem um gatilho pré/pós) Escrita Transação de item único
Substituir (por um gatilho pré/pós) Escrever e Ler Transação com vários itens
Upsert (sem um gatilho pré/pós) Escrita Transação de item único
Upsert (com um gatilho pré/pós) Escrever e Ler Transação com vários itens
Excluir (sem um gatilho pré/pós) Escrita Transação de item único
Excluir (com um gatilho pré/pós) Escrever e Ler Transação com vários itens
Executar procedimento armazenado Escrever e Ler Transação com vários itens
Execução iniciada pelo sistema de um procedimento de fusão Escrita Transação com vários itens
Execução iniciada pelo sistema de exclusão de itens com base na expiração (TTL) de um item Escrita Transação com vários itens
Leitura Leitura Transação de item único
Feed de Alterações Lida Transação com vários itens
Leitura Paginada Lida Transação com vários itens
Consulta paginada Lida Transação com vários itens
Executar UDF como parte da consulta paginada Lida Transação com vários itens

Transações com vários itens

O Azure Cosmos DB permite escrever procedimentos armazenados, gatilhos pré/pós, funções definidas pelo usuário (UDFs) e procedimentos de mesclagem em JavaScript. O Azure Cosmos DB dá suporte nativo à execução de JavaScript dentro de seu mecanismo de banco de dados. Você pode registrar procedimentos armazenados, gatilhos pré/pós, funções definidas pelo usuário (UDFs) e procedimentos de mesclagem em um contêiner e, posteriormente, executá-los transacionalmente no mecanismo de banco de dados do Azure Cosmos DB. Escrever a lógica do aplicativo em JavaScript permite a expressão natural do fluxo de controle, escopo de variáveis, atribuição e integração de primitivos de tratamento de exceções dentro das transações de banco de dados diretamente na linguagem JavaScript.

Os procedimentos armazenados baseados em JavaScript, gatilhos, UDFs e procedimentos de mesclagem são encapsulados em uma transação ACID ambiente com isolamento de instantâneo em todos os itens dentro da partição lógica. Durante a sua execução, se o programa JavaScript lançar uma exceção, toda a transação será abortada e revertida. O modelo de programação resultante é simples, mas poderoso. Os desenvolvedores JavaScript obtêm um modelo de programação durável enquanto ainda usam suas construções de linguagem familiares e primitivas de biblioteca.

A capacidade de executar JavaScript diretamente no mecanismo de banco de dados fornece desempenho e execução transacional de operações de banco de dados em relação aos itens de um contêiner. Além disso, como o mecanismo de banco de dados do Azure Cosmos DB suporta nativamente JSON e JavaScript, não há incompatibilidade de impedância entre os sistemas de tipo de um aplicativo e o banco de dados.

Controlo da simultaneidade otimista

O controle de simultaneidade otimista permite que você evite atualizações e exclusões perdidas. Operações simultâneas e conflitantes são submetidas ao bloqueio pessimista regular do mecanismo de banco de dados hospedado pela partição lógica proprietária do item. Quando duas operações simultâneas tentam atualizar a versão mais recente de um item dentro de uma partição lógica, uma delas vencerá e a outra falhará. No entanto, se uma ou duas operações que tentam atualizar simultaneamente o mesmo item tiverem lido anteriormente um valor mais antigo do item, o banco de dados não saberá se o valor lido anteriormente por uma ou ambas as operações conflitantes foi realmente o valor mais recente do item. Felizmente, essa situação pode ser detetada com o Optimistic Concurrency Control (OCC) antes de permitir que as duas operações entrem no limite da transação dentro do mecanismo de banco de dados. O OCC protege seus dados contra a substituição acidental de alterações feitas por outras pessoas. Também impede que outros substituam acidentalmente as suas próprias alterações.

Implementando controle de simultaneidade otimista usando cabeçalhos ETag e HTTP

Cada item armazenado em um contêiner do Azure Cosmos DB tem uma propriedade definida pelo _etag sistema. O valor do _etag é gerado e atualizado automaticamente pelo servidor toda vez que o item é atualizado. _etag pode ser usado com o cabeçalho de solicitação fornecido if-match pelo cliente para permitir que o servidor decida se um item pode ser atualizado condicionalmente. O valor do if-match cabeçalho corresponde ao valor do _etag no servidor, o item é então atualizado. Se o valor do cabeçalho da solicitação não for mais atual, o servidor rejeitará a operação com uma mensagem de if-match resposta "HTTP 412 Precondition failure". Em seguida, o cliente pode buscar novamente o item para adquirir a versão atual do item no servidor ou substituir a versão do item no servidor com seu próprio _etag valor para o item. Além disso, _etag pode ser usado com o if-none-match cabeçalho para determinar se uma rebusca de um recurso é necessária.

O valor do _etag item muda sempre que o item é atualizado. Para operações de substituição de item, if-match deve ser explicitamente expresso como parte das opções de solicitação. Para obter um exemplo, consulte o código de exemplo no GitHub. _etag os valores são verificados implicitamente para todos os itens escritos tocados pelo procedimento armazenado. Se algum conflito for detetado, o procedimento armazenado reverterá a transação e lançará uma exceção. Com esse método, todas ou nenhuma gravação dentro do procedimento armazenado é aplicada atomicamente. Este é um sinal para o aplicativo para reaplicar atualizações e repetir a solicitação do cliente original.

Controle de simultaneidade otimista e distribuição global

As atualizações simultâneas de um item são submetidas ao OCC pela camada de protocolo de comunicação do Azure Cosmos DB. Para contas do Azure Cosmos DB configuradas para gravações de região única, o Azure Cosmos DB garante que a versão do lado do cliente do item que você está atualizando (ou excluindo) seja a mesma que a versão do item no contêiner do Azure Cosmos DB. Isso garante que suas gravações sejam protegidas contra serem substituídas acidentalmente pelas gravações de outras pessoas e vice-versa. Em um ambiente multiusuário, o controle de simultaneidade otimista protege você contra excluir ou atualizar acidentalmente a versão errada de um item. Como tal, os itens são protegidos contra os infames problemas de "atualização perdida" ou "exclusão perdida".

Em uma conta do Azure Cosmos DB configurada com gravações de várias regiões, os dados podem ser confirmados independentemente em regiões secundárias se corresponderem _etag aos dados na região local. Depois que novos dados são confirmados localmente em uma região secundária, eles são mesclados no hub ou na região primária. Se a política de resolução de conflitos mesclar os novos dados na região do hub, esses dados serão replicados globalmente com o novo _etag. Se a política de resolução de conflitos rejeitar os novos dados, a região secundária será revertida para os dados originais e _etag.

Próximos passos

Saiba mais sobre transações de banco de dados e controle de simultaneidade otimista nos seguintes artigos: