Transações e controlo de simultaneidade otimista

APLICA-SE A: NoSQL

As transações de bases de dados fornecem um modelo de programação seguro e previsível para lidar com alterações simultâneas aos dados. As bases de dados relacionais tradicionais, como SQL Server, permitem-lhe escrever a lógica de negócio através de procedimentos armazenados e/ou acionadores, enviam-na para o servidor para execução diretamente no motor de base de dados. Com as bases de dados relacionais tradicionais, tem de lidar com duas linguagens de programação diferentes da linguagem de programação de aplicações (não transacionais), como JavaScript, Python, C#, Java, etc. e a linguagem de programação transacional (por exemplo, T-SQL) que é executada nativamente pela base de dados.

O motor de base de dados no Azure Cosmos DB suporta transações completas compatíveis com ACID (Atomicidade, Consistência, Isolamento, Durabilidade) com isolamento de instantâneos. Todas as operações da base de dados no âmbito da partição lógica de um contentor são executadas de forma transacional no motor de base de dados que é alojado pela réplica da partição. Estas operações incluem operações de escrita (atualização de um ou mais itens na partição lógica) e operações de leitura. A tabela seguinte 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 acionador pré/post) Escrita Transação de item único
Inserir (com um acionador pré/post) Escrever e Ler Transação de vários itens
Substituir (sem um acionador pré/post) Escrita Transação de item único
Substituir (por um acionador pré/post) Escrever e Ler Transação de vários itens
Upsert (sem um acionador pré/post) Escrita Transação de item único
Upsert (com um acionador pré/post) Escrever e Ler Transação de vários itens
Eliminar (sem um acionador pré/post) Escrita Transação de item único
Eliminar (com um acionador pré/post) Escrever e Ler Transação de vários itens
Executar procedimento armazenado Escrever e Ler Transação de vários itens
Execução iniciada pelo sistema de um procedimento de intercalação Escrita Transação de vários itens
Execução iniciada pelo sistema de eliminação de itens com base na expiração (TTL) de um item Escrita Transação de vários itens
Leitura Leitura Transação de item único
Feed de Alterações Leitura Transação de vários itens
Leitura Paginada Leitura Transação de vários itens
Consulta Paginada Leitura Transação de vários itens
Executar o UDF como parte da consulta paginada Leitura Transação de vários itens

Transações de vários itens

O Azure Cosmos DB permite-lhe escrever procedimentos armazenados, acionadores pré/post, funções definidas pelo utilizador (UDFs) e procedimentos de intercalação no JavaScript. O Azure Cosmos DB suporta nativamente a execução de JavaScript dentro do motor de base de dados. Pode registar procedimentos armazenados, acionadores pré/post, funções definidas pelo utilizador (UDFs) e intercalar procedimentos num contentor e, posteriormente, executá-los de forma transacional no motor de base de dados do Azure Cosmos DB. Escrever lógica de aplicação em JavaScript permite uma expressão natural do fluxo de controlo, âmbito de variáveis, atribuição e integração de primitivos de processamento de exceções nas transações de base de dados diretamente na linguagem JavaScript.

Os procedimentos armazenados, acionadores, UDFs e procedimentos de intercalação baseados em JavaScript são encapsulados numa 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 emitir uma exceção, toda a transação é abortada e revertida. O modelo de programação resultante é simples, mas poderoso. Os programadores de JavaScript obtêm um modelo de programação durável enquanto ainda utilizam as construções de linguagem familiares e os primitivos da biblioteca.

A capacidade de executar o JavaScript diretamente no motor de base de dados fornece desempenho e execução transacional de operações de base de dados em relação aos itens de um contentor. Além disso, uma vez que o motor de base de dados do Azure Cosmos DB suporta nativamente JSON e JavaScript, não existem erros de correspondência entre os sistemas de tipo de uma aplicação e a base de dados.

Controlo da simultaneidade otimista

O controlo de simultaneidade otimista permite-lhe evitar atualizações e eliminações perdidas. As operações simultâneas em conflito estão sujeitas ao bloqueio pessimista regular do motor de base de dados alojado 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 numa partição lógica, uma delas ganha e a outra falha. No entanto, se uma ou duas operações que tentam atualizar em simultâneo o mesmo item tinham lido anteriormente um valor mais antigo do item, a base de dados não sabe se o valor lido anteriormente por ou ambas as operações em conflito era, de facto, o valor mais recente do item. Felizmente, esta situação pode ser detetada com o Controlo de Simultaneidade Otimista (OCC) antes de permitir que as duas operações introduzam o limite de transação dentro do motor de base de dados. O OCC protege os seus dados de substituir acidentalmente as alterações efetuadas por outras pessoas. Também impede que outras pessoas substituam acidentalmente as suas próprias alterações.

Implementar o controlo de simultaneidade otimista com cabeçalhos ETag e HTTP

Cada item armazenado num contentor do Azure Cosmos DB tem uma propriedade definida pelo _etag sistema. O valor do _etag é gerado e atualizado automaticamente pelo servidor sempre que o item é atualizado. _etag pode ser utilizado com o cabeçalho de pedido fornecido pelo if-match cliente para permitir que o servidor decida se um item pode ser atualizado condicionalmente. O valor do if-match cabeçalho corresponde ao valor de _etag no servidor, o item é atualizado. Se o valor do cabeçalho do if-match pedido já não estiver atualizado, o servidor rejeita a operação com uma mensagem de resposta "Falha de pré-condição HTTP 412". Em seguida, o cliente pode obter novamente o item para adquirir a versão atual do item no servidor ou substituir a versão do item no servidor com o seu próprio _etag valor para o item. Além disso, _etag pode ser utilizado com o if-none-match cabeçalho para determinar se é necessária uma nova correspondência de um recurso.

O valor do _etag item é alterado sempre que o item é atualizado. Para operações de substituição de itens, if-match tem de ser expressa explicitamente como parte das opções de pedido. Por exemplo, veja o código de exemplo no GitHub. _etag os valores são verificados implicitamente para todos os itens escritos tocados pelo procedimento armazenado. Se for detetado algum conflito, o procedimento armazenado reverterá a transação e gerará uma exceção. Com este método, todas ou nenhuma escrita no procedimento armazenado é aplicada atomicamente. Este é um sinal para a aplicação para reaplicar atualizações e repetir o pedido de cliente original.

Controlo de simultaneidade otimista e distribuição global

As atualizações simultâneas de um item estão sujeitas ao OCC pela camada de protocolo de comunicação do Azure Cosmos DB. Para contas do Azure Cosmos DB configuradas para escritas de região única, o Azure Cosmos DB garante que a versão do lado do cliente do item que está a atualizar (ou a eliminar) é a mesma que a versão do item no contentor do Azure Cosmos DB. Isto garante que as suas escritas estão protegidas contra serem substituídas acidentalmente pelas escritas de outras pessoas e vice-versa. Num ambiente multiutilizador, o controlo de simultaneidade otimista protege-o de eliminar 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 "eliminação perdida".

Numa conta do Azure Cosmos DB configurada com escritas em várias regiões, os dados podem ser consolidados de forma independente em regiões secundárias se _etag corresponderem aos dados na região local. Assim que os novos dados forem consolidados localmente numa região secundária, serão intercalados no hub ou na região primária. Se a política de resolução de conflitos intercalar os novos dados na região do hub, estes 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.

Passos seguintes

Saiba mais sobre as transações de bases de dados e o controlo de simultaneidade otimista nos seguintes artigos: