{"id":5437,"date":"2018-07-09T06:35:10","date_gmt":"2018-07-09T13:35:10","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=5437"},"modified":"2025-06-13T19:28:04","modified_gmt":"2025-06-14T02:28:04","slug":"multi-document-transactions-acid-couchbase-2","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/multi-document-transactions-acid-couchbase-2\/","title":{"rendered":"Transa\u00e7\u00f5es com v\u00e1rios documentos: ACID e Couchbase Parte 2"},"content":{"rendered":"<div class=\"paragraph\">\n<p><em><strong>Observa\u00e7\u00e3o importante<\/strong><\/em>: As transa\u00e7\u00f5es ACID de v\u00e1rios documentos agora est\u00e3o dispon\u00edveis no Couchbase. Veja: <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/transactions\/\">Transa\u00e7\u00f5es ACID para aplicativos NoSQL<\/a> para obter mais informa\u00e7\u00f5es!<\/p>\n<p>As transa\u00e7\u00f5es com v\u00e1rios documentos n\u00e3o foram abordadas na postagem anterior desta s\u00e9rie: <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/acid-properties-couchbase-part-1\/\">Propriedades ACID e Couchbase<\/a>. Essa postagem do blog abordou os blocos de constru\u00e7\u00e3o do ACID que o Couchbase suporta para o <em>\u00fanico<\/em> documento. Nesta postagem do blog, usaremos essa base para criar algo <em>como<\/em> uma transa\u00e7\u00e3o at\u00f4mica e distribu\u00edda de v\u00e1rios documentos.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>Isen\u00e7\u00e3o de responsabilidade: o c\u00f3digo nesta postagem do blog n\u00e3o \u00e9 recomendado para produ\u00e7\u00e3o. Trata-se de um exemplo simplificado que <em>pode<\/em> O Couchbase pode ser \u00fatil para voc\u00ea no estado em que se encontra, mas precisar\u00e1 ser aprimorado e polido antes de estar pronto para produ\u00e7\u00e3o. A inten\u00e7\u00e3o \u00e9 dar a voc\u00ea uma ideia do que seria necess\u00e1rio para aquelas situa\u00e7\u00f5es (esperamos que raras) em que voc\u00ea precisa de transa\u00e7\u00f5es de v\u00e1rios documentos com o Couchbase.<\/strong><\/p>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_a_brief_recap\">Uma breve recapitula\u00e7\u00e3o<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Na parte 1, vimos que as propriedades ACID est\u00e3o de fato dispon\u00edveis no Couchbase no n\u00edvel de documento \u00fanico. Para casos de uso em que os documentos podem armazenar dados juntos de forma desnormalizada, isso \u00e9 adequado. Em alguns casos, a desnormaliza\u00e7\u00e3o em um \u00fanico documento por si s\u00f3 n\u00e3o \u00e9 suficiente para atender aos requisitos. Para esse pequeno n\u00famero de casos de uso, talvez voc\u00ea queira considerar o exemplo desta postagem do blog.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Uma nota de advert\u00eancia: esta postagem do blog \u00e9 uma <em>in\u00edcio<\/em> ponto para voc\u00ea. Seu caso de uso, suas necessidades t\u00e9cnicas, os recursos do Couchbase Server e os casos extremos com os quais voc\u00ea se importa variam. Atualmente, n\u00e3o existe uma abordagem \u00fanica para todos os casos.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_multi_document_transactions_example\">Exemplo de transa\u00e7\u00f5es com v\u00e1rios documentos<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Vamos nos concentrar em uma opera\u00e7\u00e3o simples para manter o c\u00f3digo simples. Para casos mais avan\u00e7ados, voc\u00ea pode usar esse c\u00f3digo como base e, possivelmente, gen\u00e9rico e adapt\u00e1-lo como achar melhor.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Digamos que estejamos trabalhando em um jogo. Esse jogo envolve a cria\u00e7\u00e3o e a administra\u00e7\u00e3o de fazendas (parece loucura, eu sei). Suponha que, nesse jogo, voc\u00ea tenha um celeiro que cont\u00e9m um certo n\u00famero de galinhas. Seu amigo tamb\u00e9m tem um celeiro com um certo n\u00famero de galinhas. Em algum momento, voc\u00ea pode querer transferir algumas galinhas do seu galp\u00e3o para o galp\u00e3o de um amigo.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Nesse caso, a normaliza\u00e7\u00e3o de dados provavelmente n\u00e3o ajudar\u00e1. Porque:<\/p>\n<\/div>\n<div class=\"ulist\">\n<ul>\n<li>Um \u00fanico documento contendo todos os celeiros simplesmente n\u00e3o funcionar\u00e1 em um jogo de tamanho significativo.<\/li>\n<li>N\u00e3o faz sentido que seu documento do celeiro contenha o documento do celeiro de seu amigo (ou vice-versa).<\/li>\n<li>O restante da l\u00f3gica do jogo funciona bem com a atomicidade de um \u00fanico documento: s\u00f3 a transfer\u00eancia de frango \u00e9 que \u00e9 complicada.<\/li>\n<\/ul>\n<\/div>\n<div class=\"paragraph\">\n<p>Para come\u00e7ar, tudo o que temos s\u00e3o dois documentos de \"celeiro\" (Grant Barn e Miller Barn):<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11001-barn-documents-initial.png\" alt=\"Initial barn documents\" \/><\/span><\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Esse m\u00e9todo que usaremos para transferir galinhas \u00e9 chamado de \"commit de duas fases\". H\u00e1 um total de seis etapas. <a href=\"https:\/\/github.com\/couchbaselabs\/blog-source-code\/tree\/master\/Groves\/110AcidPart2\/src\">O c\u00f3digo-fonte completo est\u00e1 dispon\u00edvel no GitHub<\/a>.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><em>Depois de tirar todas as capturas de tela e escrever os exemplos de c\u00f3digo, ocorreu-me que as galinhas vivem em galinheiros, n\u00e3o em celeiros? Mas me acompanhe nessa.<\/em><\/p>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_0_transaction_document\">0) Documento de transa\u00e7\u00e3o<\/h3>\n<div class=\"paragraph\">\n<p>A primeira etapa \u00e9 criar um documento de transa\u00e7\u00e3o. Esse \u00e9 um documento que manter\u00e1 o controle da transa\u00e7\u00e3o de v\u00e1rios documentos e a <strong>estado<\/strong> da transa\u00e7\u00e3o. Criei um C# <code>Enum<\/code> com os poss\u00edveis estados usados na transa\u00e7\u00e3o. Isso ser\u00e1 um n\u00famero quando armazenado no Couchbase, mas voc\u00ea pode usar cadeias de caracteres ou outra representa\u00e7\u00e3o, se desejar.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">public enum TransactionStates\r\n{\r\n    Initial = 0,\r\n    Pending = 1,\r\n    Committed = 2,\r\n    Done = 3,\r\n    Cancelling = 4,\r\n    Cancelled = 5\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Ela come\u00e7ar\u00e1 em um estado \"Inicial\". Para essa transa\u00e7\u00e3o, temos um galp\u00e3o de \"origem\", um galp\u00e3o de \"destino\" e um certo n\u00famero de galinhas para transferir.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">var transaction = _bucket.Upsert(new Document&lt;TransactionRecord&gt;\r\n{\r\n    Id = transactionDocumentKey,\r\n    Content = new TransactionRecord\r\n    {\r\n        SourceId = source.Id,\r\n        Source = source.Value,\r\n        DestinationId = destination.Id,\r\n        Destination = destination.Value,\r\n        Amount = amountToTransfer,\r\n        State = TransactionStates.Initial\r\n    }\r\n});<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Vamos dar uma olhada nos dados novamente. Agora h\u00e1 tr\u00eas documentos. A transa\u00e7\u00e3o \u00e9 nova; os documentos do celeiro s\u00e3o os mesmos do in\u00edcio.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11002-barn-documents-initial-transaction-document.png\" alt=\"Initial multi-document transactions document\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_1_switch_to_pending\">1) Mudar para pendente<\/h3>\n<div class=\"paragraph\">\n<p>Em seguida, vamos colocar o documento da transa\u00e7\u00e3o em um estado \"pendente\". Veremos mais adiante por que o \"estado\" de uma transa\u00e7\u00e3o \u00e9 importante.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">var transCas = UpdateWithCas&lt;TransactionRecord&gt;(transaction.Id, x =&gt; x.State = TransactionStates.Pending, transaction.Document.Cas);<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Trapaceei um pouco aqui, pois estou usando um <code>UpdateWithCas<\/code> fun\u00e7\u00e3o. Farei isso muitas vezes, pois atualizar um documento usando uma opera\u00e7\u00e3o Cas pode ser um pouco verboso no .NET. Por isso, criei uma pequena fun\u00e7\u00e3o auxiliar:<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">private ulong UpdateWithCas&lt;T&gt;(string documentId, Action&lt;T&gt; act, ulong? cas = null)\r\n{\r\n    var document = _bucket.Get&lt;T&gt;(documentId);\r\n    var content = document.Value;\r\n    act(content);\r\n    var result = _bucket.Replace(new Document&lt;T&gt;\r\n    {\r\n        Cas = cas ?? document.Cas,\r\n        Id = document.Id,\r\n        Content = content\r\n    });\r\n    \/\/ NOTE: could put retr(ies) here\r\n    \/\/ or throw exception when cas values don't match\r\n    return result.Document.Cas;\r\n}<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Esse \u00e9 um m\u00e9todo auxiliar importante. Ele usa <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/optimistic-or-pessimistic-locking-which-one-should-you-pick\/\">bloqueio otimista<\/a> para atualizar um documento, mas n\u00e3o faz nenhuma nova tentativa ou tratamento de erros.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Voltemos aos dados. Ainda temos tr\u00eas documentos, mas o documento de transa\u00e7\u00e3o \"state\" foi atualizado.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11003-barns-and-transaction-pending.png\" alt=\"Multi-document Transaction pending\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_2_change_the_documents\">2) Alterar os documentos<\/h3>\n<div class=\"paragraph\">\n<p>Em seguida, realizaremos de fato as muta\u00e7\u00f5es necess\u00e1rias nos documentos do celeiro. Subtraindo uma galinha do celeiro de origem e adicionando uma galinha ao celeiro de destino. Ao mesmo tempo, vamos \"marcar\" esses documentos do celeiro com o ID do documento da transa\u00e7\u00e3o. Mais uma vez, voc\u00ea ver\u00e1 por que isso \u00e9 importante mais tarde. Tamb\u00e9m armazenarei os valores Cas dessas muta\u00e7\u00f5es, pois eles ser\u00e3o necess\u00e1rios mais tarde ao fazer outras altera\u00e7\u00f5es nesses documentos.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">var sourceCas = UpdateWithCas&lt;Barn&gt;(source.Id, x =&gt; { x.Chickens -= amountToTransfer; x.Transaction = transaction.Id; });\r\n\r\nvar destCas = UpdateWithCas&lt;Barn&gt;(destination.Id, x =&gt; { x.Chickens += amountToTransfer; x.Transaction = transaction.Id; });<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Nesse ponto, o c\u00f3digo moveu uma galinha entre celeiros. Observe tamb\u00e9m a \"etiqueta\" de transa\u00e7\u00e3o nos galp\u00f5es.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11004-barns-tagged-and-transaction-pending.png\" alt=\"Barns tagged with transaction\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_3_switch_to_committed\">3) Mudar para comprometido<\/h3>\n<div class=\"paragraph\">\n<p>At\u00e9 agora, tudo bem. As muta\u00e7\u00f5es foram conclu\u00eddas; \u00e9 hora de marcar a transa\u00e7\u00e3o como \"confirmada\".<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">transCas = UpdateWithCas&lt;TransactionRecord&gt;(transaction.Id, x =&gt; x.State = TransactionStates.Committed, transCas);<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>A \u00fanica coisa que mudou foi o \"estado\" da transa\u00e7\u00e3o.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11005-barn-documents-tags-transaction-committed.png\" alt=\"Transaction committed\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_4_remove_transaction_tags\">4) Remover as tags de transa\u00e7\u00e3o<\/h3>\n<div class=\"paragraph\">\n<p>Agora que a transa\u00e7\u00e3o de v\u00e1rios documentos est\u00e1 em um estado \"confirmado\", os celeiros n\u00e3o precisam mais saber que fazem parte de uma transa\u00e7\u00e3o. Remova essas \"tags\" dos celeiros.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">UpdateWithCas&lt;Barn&gt;(source.Id, x =&gt; { x.Transaction = null; }, sourceCas);\r\nUpdateWithCas&lt;Barn&gt;(destination.Id, x =&gt; { x.Transaction = null; }, destCas);<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Agora os celeiros est\u00e3o livres da transa\u00e7\u00e3o.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11006-barns-no-tags-transaction-committed.png\" alt=\"Multi-document Transactions tags removed\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_5_transaction_is_done\">5) A transa\u00e7\u00e3o est\u00e1 conclu\u00edda<\/h3>\n<div class=\"paragraph\">\n<p>A \u00faltima etapa \u00e9 alterar o estado da transa\u00e7\u00e3o para \"conclu\u00eddo\".<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">UpdateWithCas&lt;TransactionRecord&gt;(transaction.Id, x =&gt; x.State = TransactionStates.Done, transCas);<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Se chegamos at\u00e9 aqui, ent\u00e3o a transa\u00e7\u00e3o com v\u00e1rios documentos est\u00e1 conclu\u00edda. Os galp\u00f5es t\u00eam o n\u00famero correto de galinhas ap\u00f3s a transfer\u00eancia.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11007-transaction-done.png\" alt=\"Transaction done\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_rollback_what_if_something_goes_wrong\">Revers\u00e3o: e se algo der errado?<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>\u00c9 perfeitamente poss\u00edvel que algo d\u00ea errado durante transa\u00e7\u00f5es com v\u00e1rios documentos. Esse \u00e9 o objetivo de uma transa\u00e7\u00e3o, na verdade. Todas as opera\u00e7\u00f5es acontecem, ou n\u00e3o acontecem.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Coloquei o c\u00f3digo das etapas 1 a 5 acima em um \u00fanico bloco try\/catch. Uma exce\u00e7\u00e3o pode ocorrer em qualquer lugar do caminho, mas vamos nos concentrar em dois pontos cr\u00edticos.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>Exce\u00e7\u00e3o durante \"pending\" (pendente)<\/strong> - Como devemos lidar se ocorrer um erro bem no meio da etapa 2? Ou seja, DEPOIS de uma galinha ser subtra\u00edda do celeiro de origem, mas ANTES de uma galinha ser adicionada ao celeiro de destino. Se n\u00e3o trat\u00e1ssemos dessa situa\u00e7\u00e3o, uma galinha desapareceria no \u00e9ter e os jogadores do jogo ficariam furiosos!<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>Exce\u00e7\u00e3o ap\u00f3s a transa\u00e7\u00e3o ser \"confirmada\"<\/strong> - A transa\u00e7\u00e3o tem um estado de \"confirmada\", mas ocorre um erro antes que as tags de transa\u00e7\u00e3o n\u00e3o estejam mais nos celeiros. Se n\u00e3o trat\u00e1ssemos disso, poderia parecer para outros processos que os celeiros ainda est\u00e3o dentro de uma transa\u00e7\u00e3o. A <em>primeiro<\/em> a transfer\u00eancia de frangos seria bem-sucedida, mas nenhum outro frango poderia ser transferido.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>O c\u00f3digo pode lidar com esses problemas dentro do <code>captura<\/code> bloco. \u00c9 aqui que o \"estado\" da transa\u00e7\u00e3o entra em jogo (bem como as \"tags\" da transa\u00e7\u00e3o).<\/p>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_exception_during_pending\">Exce\u00e7\u00e3o durante \"pending\" (pendente)<\/h3>\n<div class=\"paragraph\">\n<p>Essa \u00e9 a situa\u00e7\u00e3o que faria com que as galinhas fossem perdidas e deixaria nossos jogadores irritados. O objetivo \u00e9 substituir as galinhas perdidas e fazer com que os celeiros voltem ao estado em que estavam antes da transa\u00e7\u00e3o.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Vamos supor que isso aconte\u00e7a bem no meio. Para este exemplo, temos uma nova transa\u00e7\u00e3o: transferir 1 galinha do celeiro Burrows (12 galinhas) para o celeiro White (13 galinhas).<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11013-rollback.png\" alt=\"Barns before rollback\" \/><\/span><\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Ocorreu um erro bem no meio. O celeiro de origem tem uma galinha a menos, mas o celeiro de destino n\u00e3o a recebeu.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11008-barns-inconsistent-state-with-transaction.png\" alt=\"Barns inconsistent and transaction\" \/><\/span><\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Aqui est\u00e3o as tr\u00eas etapas para a recupera\u00e7\u00e3o:<\/p>\n<\/div>\n<div class=\"sect3\">\n<h4 id=\"_1_cancel_transaction\">1) Cancelar transa\u00e7\u00e3o<\/h4>\n<div class=\"paragraph\">\n<p>Altere o estado da transa\u00e7\u00e3o para \"cancelando\". Mais tarde, mudaremos para \"cancelada\".<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">UpdateWithCas&lt;TransactionRecord&gt;(transaction.Id, x =&gt; x.State = TransactionStates.Cancelling, transactionRecord.Cas);<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>A \u00fanica coisa que mudou at\u00e9 agora foi o documento de transa\u00e7\u00e3o:<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11009-transaction-cancelling.png\" alt=\"Transaction now cancelling\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"sect3\">\n<h4 id=\"_2_revert_changes\">2) Reverter altera\u00e7\u00f5es<\/h4>\n<div class=\"paragraph\">\n<p>Em seguida, precisamos reverter o estado dos celeiros de volta ao que eram antes. Observe que isso \u00e9 necess\u00e1rio SOMENTE se o celeiro tiver uma etiqueta de transa\u00e7\u00e3o. Se n\u00e3o tiver uma etiqueta, sabemos que j\u00e1 est\u00e1 em seu estado pr\u00e9-transa\u00e7\u00e3o. Se houver uma etiqueta, remova-a.<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">UpdateWithCas&lt;Barn&gt;(source.Id, x =&gt;\r\n{\r\n    if (x.Transaction != null)\r\n    {\r\n        x.Chickens += transactionRecord.Value.Amount;\r\n        x.Transaction = null;\r\n    }\r\n});\r\n\r\nUpdateWithCas&lt;Barn&gt;(destination.Id, x =&gt;\r\n{\r\n    if (x.Transaction != null)\r\n    {\r\n        x.Chickens -= transactionRecord.Value.Amount;\r\n        x.Transaction = null;\r\n    }\r\n});<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>Agora os celeiros voltaram a ser o que eram antes.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11010-barns-rolled-back-transaction-still-cancelling.png\" alt=\"Barns rolled back\" \/><\/span><\/p>\n<\/div>\n<\/div>\n<div class=\"sect3\">\n<h4 id=\"_3_cancelled_transaction\">3) Transa\u00e7\u00e3o cancelada<\/h4>\n<div class=\"paragraph\">\n<p>A \u00faltima coisa a fazer \u00e9 definir a transa\u00e7\u00e3o como \"cancelada\".<\/p>\n<\/div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight decode:true\"><code class=\"language-C#\">UpdateWithCas&lt;TransactionRecord&gt;(transaction.Id, x =&gt; x.State = TransactionStates.Cancelled);<\/code><\/pre>\n<\/div>\n<\/div>\n<div class=\"paragraph\">\n<p>E agora, a transa\u00e7\u00e3o foi \"cancelada\".<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><span class=\"image\"><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/07\/11011-transaction-cancelled.png\" alt=\"Transaction cancelled\" \/><\/span><\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Isso preserva o n\u00famero total de galinhas no jogo. Nesse ponto, voc\u00ea ainda precisa lidar com o erro que causou a necessidade de uma revers\u00e3o. Voc\u00ea pode tentar novamente, notificar os jogadores, registrar um erro ou todas as op\u00e7\u00f5es acima.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect2\">\n<h3 id=\"_exception_during_committed\">Exce\u00e7\u00e3o durante o \"commit\"<\/h3>\n<div class=\"paragraph\">\n<p>A seguir, vamos analisar outro caso: as altera\u00e7\u00f5es nos celeiros foram conclu\u00eddas, mas as tags de transa\u00e7\u00e3o ainda n\u00e3o foram removidas. Supondo que a l\u00f3gica do jogo se preocupe com essas tags, talvez n\u00e3o seja poss\u00edvel realizar futuras transa\u00e7\u00f5es com v\u00e1rios documentos.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>A mesma l\u00f3gica de revers\u00e3o tamb\u00e9m lida com essa situa\u00e7\u00e3o.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_problems_and_edge_cases\">Problemas e casos extremos<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Esse exemplo simplificado pode ser o ideal para o seu aplicativo, mas h\u00e1 muitos casos extremos a serem considerados.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>E se o processo morrer no meio do caminho?<\/strong> Isso significa que o c\u00f3digo n\u00e3o chega nem mesmo ao <code>captura<\/code> bloqueio. Talvez seja necess\u00e1rio verificar se h\u00e1 transa\u00e7\u00f5es de v\u00e1rios documentos incompletas na inicializa\u00e7\u00e3o do aplicativo e executar a recupera\u00e7\u00e3o nesse ponto. Ou, possivelmente, ter um processo diferente de watchdog que procure transa\u00e7\u00f5es incompletas de v\u00e1rios documentos.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>E se houver uma leitura durante a transa\u00e7\u00e3o?<\/strong> Suponha que eu \"pegue\" os celeiros logo entre suas atualiza\u00e7\u00f5es. Essa ser\u00e1 uma leitura \"suja\", o que pode ser problem\u00e1tico.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>Em que estado est\u00e1 tudo o que resta?<\/strong> De quem \u00e9 a responsabilidade de concluir\/reverter transa\u00e7\u00f5es pendentes de v\u00e1rios documentos?<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>O que acontece se o mesmo documento fizer parte de duas transa\u00e7\u00f5es com v\u00e1rios documentos simultaneamente?<\/strong> Voc\u00ea precisar\u00e1 criar uma l\u00f3gica para evitar que isso aconte\u00e7a.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>O exemplo cont\u00e9m todo o estado para a revers\u00e3o. Mas se voc\u00ea quiser mais tipos de transa\u00e7\u00e3o (talvez queira transferir vacas)?<\/strong> Voc\u00ea precisaria de um identificador de tipo de transa\u00e7\u00e3o ou precisaria generalizar o c\u00f3digo de transa\u00e7\u00e3o para que pudesse abstrair o \"valor\" usado nos exemplos acima e, em vez disso, especificar a vers\u00e3o atualizada do documento.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p><strong>Outros casos extremos<\/strong>. O que acontece se houver um n\u00f3 em seu cluster que falhe no meio da transa\u00e7\u00e3o? O que acontece se voc\u00ea n\u00e3o conseguir obter os bloqueios desejados? Por quanto tempo voc\u00ea continua tentando novamente? Como voc\u00ea identifica uma transa\u00e7\u00e3o com falha (timeouts)? H\u00e1 muitos e muitos casos extremos com os quais lidar. Voc\u00ea deve testar exaustivamente todas as condi\u00e7\u00f5es que espera encontrar na produ\u00e7\u00e3o. E, no final, talvez voc\u00ea queira considerar algum tipo de estrat\u00e9gia de atenua\u00e7\u00e3o. Se voc\u00ea detectar um problema ou encontrar um bug, poder\u00e1 dar alguns frangos de gra\u00e7a para todas as partes envolvidas depois de corrigir o bug.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_other_options\">Outras op\u00e7\u00f5es<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Nossa equipe de engenharia tem feito experimentos com <strong>Transa\u00e7\u00f5es RAMP no lado do cliente<\/strong>. RAMP (Read Atomic Multi-Partition) \u00e9 uma forma de garantir a visibilidade at\u00f4mica em <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/distributed-databases-overview\/\">bancos de dados distribu\u00eddos<\/a>. Para obter mais informa\u00e7\u00f5es, consulte <a href=\"https:\/\/rustyrazorblade.com\/post\/2015\/ramp-made-easy\/\">RAMP facilitado<\/a> por Jon Haddad ou <a href=\"https:\/\/www.bailis.org\/blog\/scalable-atomic-visibility-with-ramp-transactions\/\">Visibilidade at\u00f4mica dimension\u00e1vel com transa\u00e7\u00f5es RAMP<\/a> por Peter Bailis.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>O exemplo mais maduro criado para o Couchbase \u00e9 o do <a href=\"https:\/\/github.com\/subalakr\/ramptransactionsimple\">Graham Pople usando o Java SDK<\/a>. <strong>Esta tamb\u00e9m n\u00e3o \u00e9 uma biblioteca pronta para produ\u00e7\u00e3o.<\/strong> No entanto, Graham est\u00e1 fazendo algumas coisas interessantes com transa\u00e7\u00f5es de v\u00e1rios documentos no lado do cliente. Fique ligado!<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Outra op\u00e7\u00e3o \u00e9 o software livre <a href=\"https:\/\/ndescribe.atlassian.net\/wiki\/spaces\/DOC\/pages\/1081383\/Transactional+Documents\">Biblioteca NDescribe<\/a> por Iain Cartledge (que \u00e9 um <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/get-to-know-couchbase-community-iain-cartledge\/\">Campe\u00e3o da comunidade Couchbase<\/a>).<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Por fim, d\u00ea uma olhada no <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/saga-pattern-implement-business-transactions-using-microservices-part\/\">Padr\u00e3o Saga<\/a>que \u00e9 especialmente \u00fatil para transa\u00e7\u00f5es de v\u00e1rios documentos entre microsservi\u00e7os.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"sect1\">\n<h2 id=\"_conclusion\">Conclus\u00e3o<\/h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Esta postagem do blog falou sobre como usar as primitivas ACID dispon\u00edveis no Couchbase para criar um tipo de transa\u00e7\u00e3o at\u00f4mica de v\u00e1rios documentos para um banco de dados distribu\u00eddo. Isso ainda n\u00e3o \u00e9 um substituto completamente s\u00f3lido para o ACID, mas \u00e9 suficiente para o que a grande maioria dos aplicativos modernos baseados em microsservi\u00e7os precisa. Para a pequena porcentagem de casos de uso que precisam de garantias transacionais adicionais, o Couchbase continuar\u00e1 a inovar ainda mais.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Agradecemos a Mike Goldsmith, Graham Pople e Shivani Gupta, que ajudaram a revisar esta publica\u00e7\u00e3o do blog.<\/p>\n<\/div>\n<div class=\"paragraph\">\n<p>Se voc\u00ea estiver ansioso para aproveitar os benef\u00edcios de um banco de dados distribu\u00eddo como o Couchbase, mas ainda tiver d\u00favidas sobre as transa\u00e7\u00f5es com v\u00e1rios documentos, entre em contato conosco! Voc\u00ea pode fazer perguntas na se\u00e7\u00e3o <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/forums\/\">F\u00f3runs do Couchbase<\/a> ou pode entrar em contato comigo pelo telefone <a href=\"https:\/\/twitter.com\">Twitter @mgroves<\/a>.<\/p>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Important note: Multi-Document ACID Transactions are now available in Couchbase. See: ACID Transactions for NoSQL Applications for more information! Multi-document transactions were not covered in the previous post in this series: ACID Properties and Couchbase. That blog post covered the [&hellip;]<\/p>","protected":false},"author":71,"featured_media":5109,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1811,1816],"tags":[9499],"ppma_author":[8937],"class_list":["post-5437","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-couchbase-server","tag-acid-transactions"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.2 (Yoast SEO v26.2) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Multi-document transactions: ACID and Couchbase Part 2<\/title>\n<meta name=\"description\" content=\"Multi-document transactions are possible using the single-document ACID properties of Couchbase Server and some client-side code.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/pt\/multi-document-transactions-acid-couchbase-2\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Multi-document transactions: ACID and Couchbase Part 2\" \/>\n<meta property=\"og:description\" content=\"Multi-document transactions are possible using the single-document ACID properties of Couchbase Server and some client-side code.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/multi-document-transactions-acid-couchbase-2\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-07-09T13:35:10+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T02:28:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"767\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Matthew Groves\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@mgroves\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matthew Groves\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/\"},\"author\":{\"name\":\"Matthew Groves\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58\"},\"headline\":\"Multi-document transactions: ACID and Couchbase Part 2\",\"datePublished\":\"2018-07-09T13:35:10+00:00\",\"dateModified\":\"2025-06-14T02:28:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/\"},\"wordCount\":1996,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg\",\"keywords\":[\"ACID transactions\"],\"articleSection\":[\".NET\",\"Couchbase Server\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/\",\"name\":\"Multi-document transactions: ACID and Couchbase Part 2\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg\",\"datePublished\":\"2018-07-09T13:35:10+00:00\",\"dateModified\":\"2025-06-14T02:28:04+00:00\",\"description\":\"Multi-document transactions are possible using the single-document ACID properties of Couchbase Server and some client-side code.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg\",\"width\":1920,\"height\":767},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Multi-document transactions: ACID and Couchbase Part 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58\",\"name\":\"Matthew Groves\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ba51e6aacc53995c323a634e4502ef54\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g\",\"caption\":\"Matthew Groves\"},\"description\":\"Matthew D. Groves is a guy who loves to code. It doesn't matter if it's C#, jQuery, or PHP: he'll submit pull requests for anything. He has been coding professionally ever since he wrote a QuickBASIC point-of-sale app for his parent's pizza shop back in the 90s. He currently works as a Senior Product Marketing Manager for Couchbase. His free time is spent with his family, watching the Reds, and getting involved in the developer community. He is the author of AOP in .NET, Pro Microservices in .NET, a Pluralsight author, and a Microsoft MVP.\",\"sameAs\":[\"https:\/\/crosscuttingconcerns.com\",\"https:\/\/x.com\/mgroves\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/matthew-groves\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Transa\u00e7\u00f5es com v\u00e1rios documentos: ACID e Couchbase Parte 2","description":"As transa\u00e7\u00f5es de v\u00e1rios documentos s\u00e3o poss\u00edveis usando as propriedades ACID de documento \u00fanico do Couchbase Server e algum c\u00f3digo do lado do cliente.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/pt\/multi-document-transactions-acid-couchbase-2\/","og_locale":"pt_BR","og_type":"article","og_title":"Multi-document transactions: ACID and Couchbase Part 2","og_description":"Multi-document transactions are possible using the single-document ACID properties of Couchbase Server and some client-side code.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/multi-document-transactions-acid-couchbase-2\/","og_site_name":"The Couchbase Blog","article_published_time":"2018-07-09T13:35:10+00:00","article_modified_time":"2025-06-14T02:28:04+00:00","og_image":[{"width":1920,"height":767,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg","type":"image\/jpeg"}],"author":"Matthew Groves","twitter_card":"summary_large_image","twitter_creator":"@mgroves","twitter_misc":{"Written by":"Matthew Groves","Est. reading time":"12 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/"},"author":{"name":"Matthew Groves","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58"},"headline":"Multi-document transactions: ACID and Couchbase Part 2","datePublished":"2018-07-09T13:35:10+00:00","dateModified":"2025-06-14T02:28:04+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/"},"wordCount":1996,"commentCount":1,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg","keywords":["ACID transactions"],"articleSection":[".NET","Couchbase Server"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/","url":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/","name":"Transa\u00e7\u00f5es com v\u00e1rios documentos: ACID e Couchbase Parte 2","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg","datePublished":"2018-07-09T13:35:10+00:00","dateModified":"2025-06-14T02:28:04+00:00","description":"As transa\u00e7\u00f5es de v\u00e1rios documentos s\u00e3o poss\u00edveis usando as propriedades ACID de documento \u00fanico do Couchbase Server e algum c\u00f3digo do lado do cliente.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/05\/105-acid-properties-hero.jpg","width":1920,"height":767},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/multi-document-transactions-acid-couchbase-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Multi-document transactions: ACID and Couchbase Part 2"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/3929663e372020321b0152dc4fa65a58","name":"Matthew Groves","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/ba51e6aacc53995c323a634e4502ef54","url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","caption":"Matthew Groves"},"description":"Matthew D. Groves \u00e9 um cara que adora programar. N\u00e3o importa se \u00e9 C#, jQuery ou PHP: ele enviar\u00e1 solicita\u00e7\u00f5es de pull para qualquer coisa. Ele tem programado profissionalmente desde que escreveu um aplicativo de ponto de venda QuickBASIC para a pizzaria de seus pais nos anos 90. Atualmente, ele trabalha como gerente s\u00eanior de marketing de produtos da Couchbase. Seu tempo livre \u00e9 passado com a fam\u00edlia, assistindo aos Reds e participando da comunidade de desenvolvedores. Ele \u00e9 autor de AOP in .NET, Pro Microservices in .NET, autor da Pluralsight e Microsoft MVP.","sameAs":["https:\/\/crosscuttingconcerns.com","https:\/\/x.com\/mgroves"],"url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/matthew-groves\/"}]}},"authors":[{"term_id":8937,"user_id":71,"is_guest":0,"slug":"matthew-groves","display_name":"Matthew Groves","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/70feb1b28a099ad0112b8d21fe1e81e1a4524beed3e20b7f107d5370e85a07ab?s=96&d=mm&r=g","author_category":"","last_name":"Groves","first_name":"Matthew","job_title":"","user_url":"https:\/\/crosscuttingconcerns.com","description":"Matthew D. Groves \u00e9 um cara que adora programar.  N\u00e3o importa se \u00e9 C#, jQuery ou PHP: ele enviar\u00e1 solicita\u00e7\u00f5es de pull para qualquer coisa.  Ele tem programado profissionalmente desde que escreveu um aplicativo de ponto de venda QuickBASIC para a pizzaria de seus pais nos anos 90.  Atualmente, ele trabalha como gerente s\u00eanior de marketing de produtos da Couchbase. Seu tempo livre \u00e9 passado com a fam\u00edlia, assistindo aos Reds e participando da comunidade de desenvolvedores.  Ele \u00e9 autor de AOP in .NET, Pro Microservices in .NET, autor da Pluralsight e Microsoft MVP."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/5437","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/71"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=5437"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/5437\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/5109"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=5437"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=5437"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=5437"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=5437"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}