Banco de Dados

19 jul, 2018

Transações multi documento no MongoDB 4.0

Publicidade

No mês de junho participei do MongoDB Word 2018, e tive a oportunidade de assistir muitas palestras bacanas. Havia uma trilha só com palestras sobre transações, e eu assisti algumas.

Transação multi documento é um recurso fantástico – se usado corretamente – e neste artigo eu gostaria de compartilhar algumas coisas legais que eu aprendi sobre esse recurso.

NoSQL <> Relacional

Adoro trabalhar com MongoDB e sou extremamente grata por todos os meus projetos, mas tremo quando ouço clientes, alunos amigos afirmarem que, com as transações, poderão usar o MongoDB para tudo.

Isso tem cheiro de confusão! As transações são muito legais e realmente adicionam super poderes para os nossos projetos, mas a minha primeira consideração sobre este recurso é que deve ser usado com cuidado e no momento certo!

Desculpem me, amigos, mas a liberdade de escolher o tipo de SGBD traz a responsabilidade de escolhermos o mais adequado (parafraseando o Tio Ben do Homem Aranha). Digo isso porque o MongoDB sempre teve o conceito de transação, mas a transação era limitada a um único documento.

Com a versão 4.0, as transações passaram a ser multi documentos. Vou insistir neste aspecto, porque acho que ele é extremamente perigoso e pode comprometer seriamente o sucesso do seu projeto.

Imagine que você tem um banco de dados relacional, lindo e funcional! Por uma diretriz da empresa, você precisa migrar os dados para o MongoDB.

As três principais tabelas do seu banco de dados são representadas no diagrama entidade-relacionamento da figura 1.

As regras para uso destas tabelas podem ser descritas da seguinte maneira:

  • Um cliente compra um produto que existe no Banco de Dados;
  • Um pedido é criado;
  • Os itens do pedido são adicionados, de forma que não sejam incluídos itens sem um pedido correspondente.

Ou seja, no momento da compra, existe uma transação que garante que o pedido e todos os itens são incluídos juntos, como uma unidade atômica.

Para migrar os seus dados para o MongoDB 4.0, você precisará entender os seus dados e modelá-los de forma adequada. Conselho de amiga: erros de modelagem acabam com o seu projeto, pois aumentam a complexidade e comprometem o desempenho.

Voltando ao nosso exemplo, seria um tiro no tornozelo criar três coleções (equivalentes às tabelas existentes) e uma transação para cada operação de inclusão. Uma das maneiras de atender a esta necessidade de negócio, seria criar um único documento, como o da figura 2, e neste caso, não seria necessário criar uma transação multi documento. Entendem a sutileza? Se você modelar corretamente, conseguirá identificar quando usar e quando não usar transações.

Figura 1 – Diagrama Entidade-Relacionamento do BD legado
Figura 2 – Proposta de Modelagem

Resumindo: se você criou seu banco de dados no MongoDB como se estivesse criando um banco de dados relacional, você errou!

Mas e a solução para o problema de migrar os dados de um banco de dados relacional para o MongoDB?

Por mais que a modelagem de dados seja uma etapa chata e cara, ela minimiza a chances de erros. E quando falamos de bancos de dados com volumes consideráveis, uma correção é arriscada, demorada e cara! (Juro que não é propaganda da Arquitetura de Dados). Sendo assim, para adotar um banco de dados tão poderoso como o MongoDB, invista tempo em modelar seus dados corretamente, de forma que, se necessário, você use as transações multi documentos.

Replicação

Um dos recursos mais legais do MongoDB é a replicação nativa. A replicação é um recurso para garantir a alta disponibilidade do seu banco de dados.

De maneira básica e simplista, os dados são inseridos em um servidor e replicados para outros. Se o seu servidor principal parar, a sua aplicação continuará funcionando (sem nenhuma alteração!), porque um dos servidores que estava recebendo os dados replicados assume a posição de servidor principal.

Usando a nomenclatura adequada, temos um Primary que recebe os dados do driver e os Secondary, que recebem os dados replicados. Se o primary cair, um dos secondary assume essa posição (de primary). Veja na figura 3, abaixo:

Figura 3 – Replicação

E por que estou falando isso se o artigo é sobre transações multi documentos? Porque na versão 4.0 do MongoDB, as transações estão disponíveis em um ambiente replicado, mas não estão disponíveis em um ambiente particionado, ou seja, que usa o sharding.

O que é uma transação?

Escrevi um artigo no meu blog DB4Begnners.com falando sobre transações, e lá usei a seguinte definição: “Uma transação é a sequência de operações tratada como um bloco único e indivisível. Uma transação é executada na sua totalidade ou não é executada, então, se falhar por qualquer motivo, qualquer alteração no banco de dados que possa ter efeito na transação é desfeita. Essa propriedade “tudo ou nada” é conhecida como ATOMICIDADE.

Uma transação é uma unidade única; suas ações não podem ser mescladas com outras operações de banco de dados que não participam da transação. O sistema de gerenciamento de banco de dados (SGBD) precisa tomar ações especiais para garantir que as transações funcionem corretamente, sem interferência de comandos de banco de dados executados de forma simultânea. Essa característica é chamada de ISOLAMENTO.

Para garantir que o banco de dados não perca uma transação concluída com êxito antes de uma falha, as ações de uma transação devem ser persistidas. Além disso, os resultados de uma transação só podem ser desfeitos por outra transação. Essa propriedade é conhecida como DURABILIDADE.

Devido a essas três propriedades, uma transação deve preservar a consistência do banco de dados, e essa propriedade é conhecida como CONSISTÊNCIA. Essas são as propriedades ACID.

E o MongoDB?

Na versão 4.0, o MongoDB passou a ter suporte às transações multi documentos e, por consequência, às propriedades ACID. Mas o que você pode fazer dentro de uma transação? A resposta mais rápida, imediata e certeira: dentro das transações, você pode fazer CRUDs em coleções existentes, e que podem estar em BDs diferentes. Além disso, é possível também executar operações que retornam informações como, por exemplo: isMaster, buildInfo, connectionStatus.

O que não é permitido fazer dentro de uma transação?

Vou fazer uma listinha fofa daquilo que você não deve fazer dentro de uma transação, mas já adianto a premissa básica: qualquer operação que altere o catálogo do banco de dados, como criar ou descartar uma coleção ou um índice, não é permitida em transações multi documento.

Sendo assim, as operações abaixo não podem ser executadas (em uma transação multi documento):

  • Ler/escrever nas coleções config, admin ou local do bancos de dados.
  • Alterar os dados das coleções do banco system.
  • Retornar o plano de consulta da operação (usar o explain).
  • Para cursores criados fora de transações, você não pode chamar método getMore dentro de uma transação.
  • Para cursores criados em uma transação, você não pode chamar método getMore fora da transação.
  • Operações como createUser, getParameter, count, não são CRUDs e não são informativas, e sendo assim, não devem ser executadas em uma transação.

Show me the code!

Agora que já conversamos sobre o que é uma transação multi documento e sobre os comandos que podem estar dentro de uma transação, chegamos ao momento de entender a sintaxe para utilização deste recurso tão poderoso.

Antes de criar a transação, é importante, entender a lógica de funcionamento:

  • 1 – Crie e abra uma sessão

Neste ponto é importante destacar que transações estão associadas a uma sessão. Isto é, você inicia uma transação para uma sessão. Não é possível ter várias transações abertas simultaneamente em uma sessão.

  • 2 – Abra a transação
  • 3 – Execute um bloco de comandos
  • 4 – Efetive a transação, salvando todos os comandos no disco, ou desfaça todos os comandos
  • 5 – Feche a sessão

É bem simples, pois é muito parecido com o que estamos acostumados no “mundo transacional”.

Vamos para um exemplo usando o Mongo Shell:

//Etapa 1: Precisamos criar as coleções
db.employees.insert( { employee: 3, status:
"OK" })
db.events.insertOne( { employee: 3, status:
{ new: "XX", old: "XX" } } )

//Etapa 2: Precisamos criar uma função que utilize
as transações
function TestTransaction () {
//Abra a sessão.
session = db.getMongo().startSession( { mode:
"primary" } );
//Abra a transação
session.startTransaction();
try{
//Escreva os comandos que precisam ser
executados como uma unidade atômica
db.employees.updateOne( { employee: 3 },
{ $set: { status: "Inactive" } } );
db.events.insertOne( { employee: 3, status:
{ new: "Inactive", old: "Active" } } );
//Faça o commit da transação
session.commitTransaction();
} catch (error) {
//Se acontecer algum erro, aborte a transação.
session.abortTransaction();
 throw error;
}
//Feche a sessão.
session.endSession();
}

//Etapa 3: Precisamos executar a nossa função
TestTransaction()
//Etapa 4: Validar os resultados
db.employees.find(

db.events.find()

Conclusão

Sou suspeita para falar do MongoDB porque é um SGBD que eu adoro! A versão 4.0 coroa a maturidade do produto. Por outro lado, a nova versão complica um pouco a vida dos arquitetos que precisam decidir qual banco de dados usar. Confesso que a escolha não é simples (assunto para os próximos artigos).

Sobre a utilização de transações multi documentos, é preciso ter um pouco de cuidado ao optar por usá-las! No MongoDB World 2018, foi dito que 90% das situações não precisarão do uso de transações. Será que a sua aplicação precisa de uma transação ou de uma revisão na modelagem? Se a sua modelagem está correta, então, ok; use as transações. Modele seu banco de dados corretamente e terá caminhado 70% rumo ao sucesso (juro que não é o meu lado AD falando: é o lado DBA MongoDB).

Outro fator importante: lembre-se que alterações no catálogo de dados (ou seja, alterações no schema) não podem ser feitas dentro de uma transação.

No próximo artigo vamos conversar sobre a construção de aplicações resilientes usando transações no MongoDB, até lá!

Referências e links

Se você ainda não conhece o MongoDB, te convido a dar uma olhada no meu blog. Publiquei nele bastante coisa sobre o MongoDB:

A documentação oficial do MongoDB é fantástica e deve ser visitada sempre! Os links abaixo são muito legais e eu usei para escrever este artigo: