Transações
Nesta página
Visão geral
Neste guia, você aprenderá a realizar uma transação no MongoDB usando o pacote Laravel MongoDB. As transações permitem que você execute uma sequência de operações de gravação que atualizam os dados somente após a confirmação da transação.
Se a transação falhar, a biblioteca PHP do MongoDB que gerencia as operações do MongoDB para o Laravel MongoDB garante que o MongoDB descarte todas as alterações feitas na transação antes que elas se tornem visíveis. Essa propriedade das transações que garante que todas as alterações em uma transação sejam aplicadas ou descartadas é chamada de atomicidade.
O MongoDB executa operações de gravação em documentos únicos atomicamente. Se você precisar de atomicidade nas operações de gravação em vários documentos ou de consistência de dados em vários documentos para suas operações, execute-as em uma transação multidocumento.
As transações multidocumento estão em conformidade com ACID porque o MongoDB garante que os dados em suas operações de transação permaneçam consistentes, mesmo que o driver encontre erros inesperados.
Saiba como realizar transações nas seguintes seções deste guia:
Dica
Para saber mais sobre transações no MongoDB, consulte Transações no manual do servidor MongoDB.
Requisitos e limitações
Para executar transações no MongoDB, você deve usar a seguinte versão e topologia do MongoDB:
MongoDB versão 4.0 ou posterior
Um sistema de conjunto de réplicas ou cluster fragmentado
O servidor MongoDB e o Laravel MongoDB têm as seguintes limitações:
Nas versões 4.2 e anteriores do MongoDB, as operações de gravação realizadas em uma transação devem estar em collections existentes. Nas versões 4.4 e posterior do MongoDB, o servidor cria automaticamente collections conforme necessário quando você executa operações de gravação em uma transação. Para saber mais sobre essa limitação, consulte Criar coleções e índices em uma transação no manual do servidor MongoDB.
O MongoDB não suporta transações aninhadas. Se você tentar iniciar uma transação dentro de outra, a extensão gerará um
RuntimeException
. Para saber mais sobre essa limitação, consulte Transações e sessões no manual do servidor MongoDB.O pacote Laravel MongoDB não suporta as características de teste de banco de dados
Illuminate\Foundation\Testing\DatabaseTransactions
eIlluminate\Foundation\Testing\RefreshDatabase
. Como solução alternativa, você pode criar migrações com o traçoIlluminate\Foundation\Testing\DatabaseMigrations
para redefinir o banco de dados após cada teste.
Executar uma transação em um retorno de chamada
Esta seção mostra como executar uma transação em uma chamada de resposta.
Ao usar esse método de execução de uma transação, todo o código no método de chamada de resposta é executado como uma única transação.
No exemplo a seguir, a transação consiste em operações de escrita que transferem os recursos de uma conta bancária, representada pelo modelo Account
, para outra conta:
DB::transaction(function () { $transferAmount = 200; $sender = Account::where('number', 223344)->first(); $sender->balance -= $transferAmount; $sender->save(); $receiver = Account::where('number', 776655)->first(); $receiver->balance += $transferAmount; $receiver->save(); });
Opcionalmente, você pode passar o número máximo de vezes para tentar novamente uma transação com falha como segundo parâmetro, conforme mostrado no exemplo de código a seguir:
DB::transaction(function() { // transaction code }, attempts: 5, );
Iniciar e confirmar uma transação
Esta seção mostra como iniciar e confirmar uma transação.
Para usar este método de iniciar e confirmar uma transação, chame o método DB::beginTransaction()
para iniciar a transação. Em seguida, chame o método DB::commit()
para encerrar a transação, que aplica todas as atualizações realizadas na transação.
No exemplo a seguir, o saldo da primeira conta é movido para a segunda conta, após o que a primeira conta é excluída:
DB::beginTransaction(); $oldAccount = Account::where('number', 223344)->first(); $newAccount = Account::where('number', 776655)->first(); $newAccount->balance += $oldAccount->balance; $newAccount->save(); $oldAccount->delete(); DB::commit();
Reverter uma transação
Esta seção mostra como reverter uma transação. Um rollback reverte todas as operações de gravação realizadas nessa transação. Isso significa que os dados são revertidos ao seu estado antes da transação.
Para executar a reversão, chame a função DB::rollback()
a qualquer momento antes de a transação ser confirmada.
No exemplo a seguir, a transação consiste em operações de gravação que transferem fundos de uma conta, representada pelo modelo Account
, para várias outras contas. Se a conta do emissor tiver fundos insuficientes, a transação será revertida e nenhum dos modelos será atualizado:
DB::beginTransaction(); $sender = Account::where('number', 223344)->first(); $receiverA = Account::where('number', 776655)->first(); $receiverB = Account::where('number', 990011)->first(); $amountA = 100; $amountB = 200; $sender->balance -= $amountA; $receiverA->balance += $amountA; $sender->balance -= $amountB; $receiverB->balance += $amountB; if ($sender->balance < 0) { // insufficient balance, roll back the transaction DB::rollback(); } else { DB::commit(); }