<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: André Moreira</title>
    <description>The latest articles on DEV Community by André Moreira (@moreiraandre).</description>
    <link>https://dev.to/moreiraandre</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F79021%2Fd1c7876c-3cfb-402c-8e09-c272dd89e56d.jpeg</url>
      <title>DEV Community: André Moreira</title>
      <link>https://dev.to/moreiraandre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moreiraandre"/>
    <language>en</language>
    <item>
      <title>Dominando Transações de Banco de Dados: Do Conceito à Prática com Laravel</title>
      <dc:creator>André Moreira</dc:creator>
      <pubDate>Tue, 21 Jul 2026 17:50:11 +0000</pubDate>
      <link>https://dev.to/moreiraandre/dominando-transacoes-de-banco-de-dados-do-conceito-a-pratica-com-laravel-k26</link>
      <guid>https://dev.to/moreiraandre/dominando-transacoes-de-banco-de-dados-do-conceito-a-pratica-com-laravel-k26</guid>
      <description>&lt;h1&gt;
  
  
  Dominando Transações de Banco de Dados: Do Conceito à Prática com Laravel
&lt;/h1&gt;

&lt;p&gt;Quantas vezes você se perguntou: "E se der erro na metade da operação?" Transações de banco de dados são o escudo invisível que protege a integridade dos seus dados. Vamos entender isso a fundo.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Problema Real
&lt;/h2&gt;

&lt;p&gt;Imagine um sistema de transferência bancária:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Débito da conta A: ✓&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Erro de rede&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Crédito na conta B: ✗&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resultado? Dinheiro desaparece. Transações resolvem isso garantindo "tudo ou nada".&lt;/p&gt;

&lt;h2&gt;
  
  
  Conceitos Fundamentais: ACID
&lt;/h2&gt;

&lt;p&gt;Antes de codar, precisamos entender os pilares:&lt;/p&gt;

&lt;h3&gt;
  
  
  Atomicidade (A)
&lt;/h3&gt;

&lt;p&gt;A transação é uma unidade indivisível. Ou todas as operações completam, ou nenhuma. Sem meio termo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consistência (C)
&lt;/h3&gt;

&lt;p&gt;O banco sempre sai de um estado válido para outro válido. Regras de negócio são respeitadas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Isolamento (I)
&lt;/h3&gt;

&lt;p&gt;Transações simultâneas não interferem umas nas outras. Cada uma vê um snapshot consistente dos dados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Durabilidade (D)
&lt;/h3&gt;

&lt;p&gt;Uma vez confirmada, os dados persistem. Mesmo com falhas de hardware.&lt;/p&gt;

&lt;h2&gt;
  
  
  Níveis de Isolamento: O Trade-off
&lt;/h2&gt;

&lt;p&gt;Aqui está o segredo que muitos desenvolvedores não dominam completamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- De menor para maior isolamento (maior custo de performance)&lt;/span&gt;

&lt;span class="k"&gt;READ&lt;/span&gt; &lt;span class="k"&gt;UNCOMMITTED&lt;/span&gt;    &lt;span class="c1"&gt;-- Dirty reads possíveis ⚠️&lt;/span&gt;
&lt;span class="k"&gt;READ&lt;/span&gt; &lt;span class="k"&gt;COMMITTED&lt;/span&gt;      &lt;span class="c1"&gt;-- Padrão do PostgreSQL (equilibrado)&lt;/span&gt;
&lt;span class="k"&gt;REPEATABLE&lt;/span&gt; &lt;span class="k"&gt;READ&lt;/span&gt;     &lt;span class="c1"&gt;-- Padrão do MySQL InnoDB&lt;/span&gt;
&lt;span class="k"&gt;SERIALIZABLE&lt;/span&gt;        &lt;span class="c1"&gt;-- Total segurança, performance limitada&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Qual usar?&lt;/strong&gt; Depende do seu caso de uso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;E-commerce: &lt;code&gt;READ COMMITTED&lt;/code&gt; geralmente basta&lt;/li&gt;
&lt;li&gt;Relatórios financeiros: &lt;code&gt;SERIALIZABLE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Blog: &lt;code&gt;READ UNCOMMITTED&lt;/code&gt; é aceitável&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Na Prática com Laravel
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Transação Básica
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Illuminate\Support\Facades\DB&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'João'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'joao@example.com'&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="nc"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'user_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'balance'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="c1"&gt;// Se algo der erro aqui, ambas operações são revertidas&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Controle Manual com Savepoints
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;beginTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Primeira operação&lt;/span&gt;
    &lt;span class="nv"&gt;$transfer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Transfer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'from_account'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'to_account'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'amount'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;savepoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Ponto de restauração&lt;/span&gt;

    &lt;span class="c1"&gt;// Operação arriscada&lt;/span&gt;
    &lt;span class="nv"&gt;$notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$transfer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;rollbackToSavepoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Volta ao ponto, mas mantém a transação&lt;/span&gt;

    &lt;span class="c1"&gt;// Agora você pode decidir: fazer retry, log, etc&lt;/span&gt;
    &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Notification failed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'transfer_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$transfer&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Commita a transferência, ignora notificação&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Definindo Nível de Isolamento
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// PostgreSQL&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// suas operações&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// MySQL&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;beginTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// suas operações&lt;/span&gt;

&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Timeout de Transação
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Evite deadlocks com timeout&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;statement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SET lock_wait_timeout = 5"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// MySQL: 5 segundos&lt;/span&gt;

&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Se travar por mais de 5s, lança exception&lt;/span&gt;
    &lt;span class="nc"&gt;AccountLock&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'account_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Simula lock&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;maxAttempts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Tenta 3 vezes antes de desistir&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Armadilhas Comuns (e como evitá-las)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Armadilha 1: Transações Muito Longas
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NÃO FAÇA ISSO&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Aqui você está lockando recursos&lt;/span&gt;
    &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchFromExternalAPI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Pode demorar 30s!&lt;/span&gt;

    &lt;span class="c1"&gt;// Enquanto isso, outras transações ficam esperando&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Solução:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Faça a operação lenta fora da transação&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetchFromExternalAPI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Rápido&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ❌ Armadilha 2: Ignorar Exceções
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// NÃO FAÇA ISSO&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'total'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Erro!&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// "Vou ignorar e seguir em frente"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Seu sistema continua inconsistente&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ❌ Armadilha 3: Transações Aninhadas Sem Cuidado
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Cada DB::transaction() é um novo nível&lt;/span&gt;
&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Transação 1&lt;/span&gt;
    &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Não é realmente uma transação aninhada!&lt;/span&gt;
        &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;Use savepoints em vez disso:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;beginTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Order&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;savepoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;rollbackToSavepoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Tenta algo diferente&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Monitoramento em Produção
&lt;/h2&gt;

&lt;p&gt;Você está monitorando suas transações? Deveria estar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Listener customizado&lt;/span&gt;
&lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'illuminate.query'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDurationInSeconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Log&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Slow transaction detected'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'sql'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'bindings'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;bindings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'time'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getDurationInSeconds&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou use ferramentas como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Datadog APM&lt;/strong&gt;: monitora transações em produção&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New Relic&lt;/strong&gt;: identifica deadlocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL logs&lt;/strong&gt;: &lt;code&gt;log_min_duration_statement = 1000&lt;/code&gt; (queries &amp;gt; 1s)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testando Transações
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Use RefreshDatabase do Laravel&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TransactionTest&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;TestCase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;RefreshDatabase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;test_transaction_rollback&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertDatabaseCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'João'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
                &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Erro!'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertDatabaseCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Rollback funcionou!&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Checklist Final: Você Está Fazendo Certo?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Transações apenas para operações que precisam de atomicidade&lt;/li&gt;
&lt;li&gt;Operações lentas fora da transação&lt;/li&gt;
&lt;li&gt;Nível de isolamento apropriado para o caso de uso&lt;/li&gt;
&lt;li&gt;Tratamento de exceções adequado&lt;/li&gt;
&lt;li&gt;Logs de transações falhadas&lt;/li&gt;
&lt;li&gt;Monitoramento em produção&lt;/li&gt;
&lt;li&gt;Testes de rollback&lt;/li&gt;
&lt;li&gt;Timeout configurado&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Próximos Passos
&lt;/h2&gt;

&lt;p&gt;Transações são fundamentais, mas há mais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distributed Transactions&lt;/strong&gt;: quando você tem múltiplos bancos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event Sourcing&lt;/strong&gt;: alternativa para auditoria&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CQRS Pattern&lt;/strong&gt;: separação leitura/escrita&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Transações não são apenas um recurso técnico—são o fundamento da confiabilidade. Dominar seus conceitos, níveis de isolamento e armadilhas é o que separa código que "funciona" de código que é &lt;strong&gt;robusto&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Qual é sua maior dificuldade com transações? Compartilha nos comentários!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Quer mergulhar mais fundo?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/docs/current/tutorial-transactions.html" rel="noopener noreferrer"&gt;PostgreSQL Transactions Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.mysql.com/doc/refman/8.0/en/commit.html" rel="noopener noreferrer"&gt;MySQL InnoDB Transactions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/database#database-transactions" rel="noopener noreferrer"&gt;Laravel Database Transactions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>laravel</category>
      <category>database</category>
      <category>backend</category>
      <category>bestpractices</category>
    </item>
    <item>
      <title>ACID em Bancos de Dados: O Que É e Por Que Deveria Importar Para Você</title>
      <dc:creator>André Moreira</dc:creator>
      <pubDate>Wed, 15 Jul 2026 18:30:42 +0000</pubDate>
      <link>https://dev.to/moreiraandre/acid-em-bancos-de-dados-o-que-e-e-por-que-deveria-importar-para-voce-4dkh</link>
      <guid>https://dev.to/moreiraandre/acid-em-bancos-de-dados-o-que-e-e-por-que-deveria-importar-para-voce-4dkh</guid>
      <description>&lt;h1&gt;
  
  
  ACID em Bancos de Dados: O Que É e Por Que Deveria Importar Para Você
&lt;/h1&gt;

&lt;p&gt;Quando você está construindo uma aplicação que depende de dados, uma pergunta inevitável surge: &lt;em&gt;como garantir que meus dados estejam sempre corretos e seguros?&lt;/em&gt; A resposta está em um acrônimo que virou padrão na indústria: &lt;strong&gt;ACID&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos entender o que ACID significa, por que é importante e como isso afeta sua escolha de banco de dados.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Que é ACID?
&lt;/h2&gt;

&lt;p&gt;ACID é um conjunto de quatro propriedades que garantem a confiabilidade das transações em um banco de dados. Cada letra representa um princípio fundamental:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A&lt;/strong&gt; - Atomicity (Atomicidade)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt; - Consistency (Consistência)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I&lt;/strong&gt; - Isolation (Isolamento)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;D&lt;/strong&gt; - Durability (Durabilidade)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos explorar cada uma delas com exemplos práticos que fazem sentido no dia a dia.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔄 Atomicity (Atomicidade)
&lt;/h2&gt;

&lt;p&gt;A atomicidade garante que uma transação seja &lt;strong&gt;"tudo ou nada"&lt;/strong&gt;. Ou ela é completamente executada, ou não é executada em absoluto.&lt;/p&gt;

&lt;p&gt;Imagine você transferindo R$ 100 de uma conta para outra em uma aplicação bancária:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Debita R$ 100 da conta A
2. Credita R$ 100 na conta B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se algo der errado entre o passo 1 e 2 (queda de energia, erro na aplicação), o banco volta tudo ao estado anterior. Você não perde R$ 100 nem deixa de ganhar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sem atomicidade:&lt;/strong&gt; Seu dinheiro desaparece, ou aparece em duas contas. Caos total.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Com atomicidade:&lt;/strong&gt; Ou a transferência completa ou é revertida. Segurança garantida.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Consistency (Consistência)
&lt;/h2&gt;

&lt;p&gt;A consistência garante que o banco de dados &lt;strong&gt;sempre esteja em um estado válido&lt;/strong&gt;. As regras que você definiu são sempre respeitadas.&lt;/p&gt;

&lt;p&gt;Vamos dizer que você tem uma regra: "Todo usuário deve ter um email válido".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'João'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email-inválido'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sem consistência:&lt;/strong&gt; O banco aceitaria esse dado inválido.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Com consistência:&lt;/strong&gt; O banco rejeita a operação porque viola a regra definida.&lt;/p&gt;

&lt;p&gt;A consistência protege a integridade dos seus dados. Constraints, triggers e validações garantem que nada "errado" entre no seu banco.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔒 Isolation (Isolamento)
&lt;/h2&gt;

&lt;p&gt;O isolamento garante que transações concorrentes &lt;strong&gt;não interfiram umas nas outras&lt;/strong&gt;. Se duas operações acontecem ao mesmo tempo, uma não vê o estado parcial da outra.&lt;/p&gt;

&lt;p&gt;Imagine dois usuários comprando o último produto em estoque simultaneamente:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sem isolamento:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usuário A verifica: 1 produto em estoque ✓&lt;/li&gt;
&lt;li&gt;Usuário B verifica: 1 produto em estoque ✓&lt;/li&gt;
&lt;li&gt;Ambos completam a compra... agora o estoque está em -1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Com isolamento:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usuário A verifica: 1 produto ✓&lt;/li&gt;
&lt;li&gt;Usuário B tenta a mesma coisa, mas o banco garante que só um consegue&lt;/li&gt;
&lt;li&gt;Um leva, o outro recebe "produto fora de estoque"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  💾 Durability (Durabilidade)
&lt;/h2&gt;

&lt;p&gt;A durabilidade garante que os dados &lt;strong&gt;não vão sumir&lt;/strong&gt;. Depois que você confirma uma transação, ela está gravada em pedra (praticamente).&lt;/p&gt;

&lt;p&gt;Mesmo se seu servidor cair na próxima nanosegundo, aquele dado está salvo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sem durabilidade:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Você faz uma venda, confirma a transação&lt;/li&gt;
&lt;li&gt;Servidor explode&lt;/li&gt;
&lt;li&gt;Ninguém sabe que a venda aconteceu&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Com durabilidade:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Você faz uma venda, confirma&lt;/li&gt;
&lt;li&gt;Servidor explode&lt;/li&gt;
&lt;li&gt;Os dados ainda lá estão, salvos permanentemente&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quando ACID Realmente Importa?
&lt;/h2&gt;

&lt;p&gt;ACID é crítico quando:&lt;/p&gt;

&lt;p&gt;✅ Dinheiro está envolvido (transações financeiras, pagamentos)&lt;br&gt;
✅ Dados sensíveis precisam estar corretos (saúde, legal)&lt;br&gt;
✅ Consistência é não-negociável (inventário, reservas)&lt;br&gt;
✅ Seu negócio depende da confiabilidade dos dados&lt;/p&gt;

&lt;p&gt;Menos crítico (mas ainda importante) quando:&lt;/p&gt;

&lt;p&gt;⚠️ Você coleta analytics ou logs (algumas perdas são aceitáveis)&lt;br&gt;
⚠️ Você trabalha com conteúdo de redes sociais (consistência eventual é ok)&lt;br&gt;
⚠️ Você precisa de escalabilidade maciça em tempo real&lt;/p&gt;
&lt;h2&gt;
  
  
  Tabela Comparativa: Qual Banco Usar?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Banco de Dados&lt;/th&gt;
&lt;th&gt;ACID&lt;/th&gt;
&lt;th&gt;Tipo&lt;/th&gt;
&lt;th&gt;Melhor Para&lt;/th&gt;
&lt;th&gt;Escalabilidade&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PostgreSQL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Sim (Completo)&lt;/td&gt;
&lt;td&gt;Relacional&lt;/td&gt;
&lt;td&gt;Aplicações críticas, financeiro, SaaS&lt;/td&gt;
&lt;td&gt;Vertical (com replicação)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MySQL/MariaDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Sim (Com InnoDB)&lt;/td&gt;
&lt;td&gt;Relacional&lt;/td&gt;
&lt;td&gt;Web apps, blogs, startups&lt;/td&gt;
&lt;td&gt;Vertical (com replicação)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Sim (Desde v4)&lt;/td&gt;
&lt;td&gt;Documento&lt;/td&gt;
&lt;td&gt;Dados semi-estruturados, prototipagem&lt;/td&gt;
&lt;td&gt;Horizontal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQLite&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Sim&lt;/td&gt;
&lt;td&gt;Relacional&lt;/td&gt;
&lt;td&gt;Apps simples, mobile, desktop&lt;/td&gt;
&lt;td&gt;Apenas arquivo local&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Oracle Database&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Sim (Completo)&lt;/td&gt;
&lt;td&gt;Relacional&lt;/td&gt;
&lt;td&gt;Grandes corporações, enterprise&lt;/td&gt;
&lt;td&gt;Vertical/Horizontal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DynamoDB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ Parcial&lt;/td&gt;
&lt;td&gt;Chave-valor&lt;/td&gt;
&lt;td&gt;Aplicações serverless na AWS&lt;/td&gt;
&lt;td&gt;Horizontal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Redis&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Não&lt;/td&gt;
&lt;td&gt;Chave-valor&lt;/td&gt;
&lt;td&gt;Cache, sessões, real-time&lt;/td&gt;
&lt;td&gt;Horizontal (com cuidado)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cassandra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Não&lt;/td&gt;
&lt;td&gt;Coluna-largura&lt;/td&gt;
&lt;td&gt;Big data, grande escala&lt;/td&gt;
&lt;td&gt;Horizontal&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Exemplo Prático com Laravel/PHP
&lt;/h2&gt;

&lt;p&gt;Se você está usando Laravel com PostgreSQL, está tendo ACID de graça:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="no"&gt;DB&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;lockForUpdate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$account&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$account&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nv"&gt;$other&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;lockForUpdate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$other&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se algo errar dentro da transação, tudo volta. PostgreSQL garante:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity:&lt;/strong&gt; Ou ambas contas são atualizadas ou nenhuma é&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency:&lt;/strong&gt; As regras do seu modelo são respeitadas&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation:&lt;/strong&gt; Outro user não consegue ler estado parcial&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durability:&lt;/strong&gt; Depois do &lt;code&gt;commit&lt;/code&gt;, aquilo não some&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Consistência Eventual: O Trade-off
&lt;/h2&gt;

&lt;p&gt;Alguns bancos NoSQL sacrificam ACID por velocidade e escalabilidade. Usam um modelo chamado &lt;strong&gt;"consistência eventual"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Significa: seus dados podem estar inconsistentes por &lt;em&gt;alguns milissegundos&lt;/em&gt;, mas eventualmente ficarão consistentes.&lt;/p&gt;

&lt;p&gt;Ideal para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contadores de views (quem liga se está 100% exato?)&lt;/li&gt;
&lt;li&gt;Social media feeds&lt;/li&gt;
&lt;li&gt;Análise de dados em larga escala&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Não recomendo para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transações financeiras&lt;/li&gt;
&lt;li&gt;Inventário de e-commerce&lt;/li&gt;
&lt;li&gt;Qualquer coisa onde a precisão é vida ou morte&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Regra de Ouro
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Se você está em dúvida, escolha ACID.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PostgreSQL e MySQL com InnoDB são extremamente rápidos e confiáveis. Você precisará de MUITA escala antes de realmente precisar abandonar ACID por NoSQL.&lt;/p&gt;

&lt;p&gt;Comece simples. Escale quando necessário. Não sobre-engenharia.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;ACID não é um conceito chato de livro de banco de dados. É a diferença entre um sistema que funciona confiável e um que perde dados aleatoriamente.&lt;/p&gt;

&lt;p&gt;Entender ACID ajuda você a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Escolher o banco de dados certo para seu projeto&lt;/li&gt;
&lt;li&gt;Escrever código mais seguro&lt;/li&gt;
&lt;li&gt;Evitar bugs sutis que aparecem em produção&lt;/li&gt;
&lt;li&gt;Dormir melhor à noite sabendo que seus dados estão seguros&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Próxima vez que alguém perguntar "Por que não usar NoSQL para tudo?", você tem a resposta. 😉&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;E você? Qual banco usa no seu projeto? Enfrentou algum problema relacionado a transações que ACID teria resolvido? Deixa nos comentários!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>backend</category>
      <category>postgres</category>
      <category>mysql</category>
    </item>
    <item>
      <title>Git com múltiplas contas: configure trabalho e pessoal no mesmo computador</title>
      <dc:creator>André Moreira</dc:creator>
      <pubDate>Wed, 24 Jun 2026 12:49:58 +0000</pubDate>
      <link>https://dev.to/moreiraandre/git-com-multiplas-contas-configure-trabalho-e-pessoal-no-mesmo-computador-p98</link>
      <guid>https://dev.to/moreiraandre/git-com-multiplas-contas-configure-trabalho-e-pessoal-no-mesmo-computador-p98</guid>
      <description>&lt;p&gt;Você já fez um commit no repositório do trabalho e percebeu que estava com o seu e-mail pessoal? Ou o contrário? Esse é um dos erros mais comuns de quem usa Git com múltiplas contas no mesmo computador.&lt;/p&gt;

&lt;p&gt;Neste tutorial você vai aprender a configurar tudo corretamente, de uma vez, usando chaves SSH separadas e &lt;code&gt;.gitconfig&lt;/code&gt; condicional — sem gambiarras.&lt;/p&gt;




&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;Por padrão o Git usa uma configuração global:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"Seu Nome"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"seu@email.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso significa que &lt;strong&gt;todos os repositórios&lt;/strong&gt; no seu computador usam o mesmo usuário. Quando você tem contas separadas (ex: &lt;code&gt;joao@empresa.com&lt;/code&gt; no GitLab da empresa e &lt;code&gt;joao@gmail.com&lt;/code&gt; no GitLab pessoal), os commits vão sair com o e-mail errado.&lt;/p&gt;

&lt;p&gt;A solução profissional envolve duas partes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Chaves SSH separadas&lt;/strong&gt; para cada conta&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.gitconfig&lt;/code&gt; condicional&lt;/strong&gt; que aplica o usuário certo — e a chave SSH certa — por pasta&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Passo 1 — Gerar as chaves SSH
&lt;/h2&gt;

&lt;p&gt;Abra o terminal e gere uma chave para cada conta. Use nomes diferentes para não sobrescrever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Chave para a conta pessoal&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"joao@gmail.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ed25519_pessoal

&lt;span class="c"&gt;# Chave para a conta do trabalho&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"joao@empresa.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ed25519_trabalho
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Por que &lt;code&gt;ed25519&lt;/code&gt;?&lt;/strong&gt; É o algoritmo mais moderno, mais seguro e recomendado pelo GitHub, GitLab e Bitbucket. Evite RSA a menos que seu servidor seja muito antigo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ao final você terá quatro arquivos em &lt;code&gt;~/.ssh/&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id_ed25519_pessoal      ← chave privada (nunca compartilhe)
id_ed25519_pessoal.pub  ← chave pública (você registra no GitLab)
id_ed25519_trabalho
id_ed25519_trabalho.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Passo 2 — Registrar as chaves no GitLab
&lt;/h2&gt;

&lt;p&gt;Para cada conta:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copie o conteúdo da chave pública:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Pessoal&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519_pessoal.pub

&lt;span class="c"&gt;# Trabalho&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519_trabalho.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Acesse &lt;strong&gt;Settings → SSH and GPG keys → New SSH key&lt;/strong&gt; na conta correspondente e cole o conteúdo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Faça isso nas &lt;strong&gt;duas contas&lt;/strong&gt;, cada uma com a sua respectiva chave pública.&lt;/p&gt;




&lt;h2&gt;
  
  
  Passo 3 — Configurar o Git por pasta (o pulo do gato)
&lt;/h2&gt;

&lt;p&gt;Aqui está o diferencial: usar o &lt;strong&gt;&lt;code&gt;includeIf&lt;/code&gt;&lt;/strong&gt; do Git para aplicar configurações diferentes dependendo de onde o repositório está — incluindo &lt;strong&gt;qual chave SSH usar&lt;/strong&gt;, sem precisar mexer no &lt;code&gt;~/.ssh/config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A ideia é simples: você organiza seus projetos em pastas separadas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/
├── projetos/
│   ├── pessoal/       ← projetos pessoais
│   └── trabalho/      ← projetos da empresa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.1 — Criar os &lt;code&gt;.gitconfig&lt;/code&gt; específicos
&lt;/h3&gt;

&lt;p&gt;Cada arquivo define o usuário &lt;strong&gt;e&lt;/strong&gt; a chave SSH que o Git deve usar naquela pasta. O &lt;code&gt;core.sshCommand&lt;/code&gt; instrui o Git a chamar o SSH com uma chave específica e ignorar qualquer configuração do &lt;code&gt;~/.ssh/config&lt;/code&gt; (o &lt;code&gt;-F /dev/null&lt;/code&gt; garante isso):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Configuração pessoal&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.gitconfig-pessoal &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
[user]
    name = João Silva
    email = joao@gmail.com
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_pessoal -F /dev/null
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="c"&gt;# Configuração do trabalho&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/.gitconfig-trabalho &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;'
[user]
    name = João Silva
    email = joao@empresa.com
[core]
    sshCommand = ssh -i ~/.ssh/id_ed25519_trabalho -F /dev/null
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;O que é &lt;code&gt;-F /dev/null&lt;/code&gt;?&lt;/strong&gt; Diz ao SSH para ignorar completamente o &lt;code&gt;~/.ssh/config&lt;/code&gt;. Isso evita que configurações globais de SSH interfiram e garante que a chave especificada em &lt;code&gt;-i&lt;/code&gt; seja a única usada. Sem essa flag, o SSH ainda pode carregar outras identidades do seu agente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3.2 — Configurar o &lt;code&gt;.gitconfig&lt;/code&gt; global com &lt;code&gt;includeIf&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Edite &lt;code&gt;~/.gitconfig&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim ~/.gitconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deixe assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[user]&lt;/span&gt;
    &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;João Silva&lt;/span&gt;
    &lt;span class="py"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;joao@gmail.com   # fallback (usado fora das pastas mapeadas)&lt;/span&gt;

&lt;span class="nn"&gt;[includeIf "gitdir:~/projetos/pessoal/"]&lt;/span&gt;
    &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;~/.gitconfig-pessoal&lt;/span&gt;

&lt;span class="nn"&gt;[includeIf "gitdir:~/projetos/trabalho/"]&lt;/span&gt;
    &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;~/.gitconfig-trabalho&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;A barra no final do caminho é obrigatória.&lt;/strong&gt; &lt;code&gt;~/projetos/trabalho/&lt;/code&gt; funciona; &lt;code&gt;~/projetos/trabalho&lt;/code&gt; não.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Passo 4 — Testar a conexão SSH
&lt;/h2&gt;

&lt;p&gt;Com os &lt;code&gt;.gitconfig&lt;/code&gt; configurados, o teste correto é deixar o &lt;strong&gt;Git invocar o SSH automaticamente&lt;/strong&gt; — sem passar a chave no comando.&lt;/p&gt;

&lt;p&gt;O detalhe importante: o &lt;code&gt;includeIf&lt;/code&gt; só é ativado dentro de um repositório git. Por isso o teste cria um repo temporário dentro de cada pasta mapeada e roda &lt;code&gt;git ls-remote&lt;/code&gt;, que faz uma conexão SSH real sem precisar de nenhum clone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Crie as pastas base se ainda não existirem&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/projetos/pessoal ~/projetos/trabalho

&lt;span class="c"&gt;# Teste da conta pessoal&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projetos/pessoal
git init .teste-pessoal &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .teste-pessoal
git ls-remote git@gitlab.com:joao-pessoal/meu-projeto.git HEAD
&lt;span class="c"&gt;# deve listar o HEAD autenticado como joao-pessoal&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; .teste-pessoal

&lt;span class="c"&gt;# Teste da conta do trabalho&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projetos/trabalho
git init .teste-trabalho &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; .teste-trabalho
git ls-remote git@gitlab.com:empresa/projeto-empresa.git HEAD
&lt;span class="c"&gt;# deve listar o HEAD autenticado como conta da empresa&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; .. &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; .teste-trabalho
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;💡 O &lt;code&gt;git init&lt;/code&gt; dentro da pasta é necessário porque o &lt;code&gt;includeIf "gitdir:..."&lt;/code&gt; só é avaliado quando o Git está operando dentro de um repositório. O &lt;code&gt;ls-remote&lt;/code&gt; faz a conexão SSH sem precisar de histórico ou commits — é o teste mais leve possível.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Se aparecer &lt;code&gt;Permission denied (publickey)&lt;/code&gt;, volte ao Passo 2 e verifique se a chave pública foi cadastrada na conta correta.&lt;/p&gt;




&lt;h2&gt;
  
  
  Passo 5 — Clonar repositórios
&lt;/h2&gt;

&lt;p&gt;Com essa abordagem, as URLs de clone continuam normais — você usa &lt;code&gt;git@gitlab.com&lt;/code&gt; em todos os casos. O Git saberá qual chave usar com base na pasta onde o repositório está:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Repositório pessoal — clone normalmente dentro de ~/projetos/pessoal/&lt;/span&gt;
git clone git@gitlab.com:joao-pessoal/meu-projeto.git ~/projetos/pessoal/meu-projeto

&lt;span class="c"&gt;# Repositório do trabalho — clone dentro de ~/projetos/trabalho/&lt;/span&gt;
git clone git@gitlab.com:empresa/projeto-empresa.git ~/projetos/trabalho/projeto-empresa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para repositórios já clonados fora da pasta certa, mova-os para a pasta correta ou defina o &lt;code&gt;sshCommand&lt;/code&gt; manualmente só naquele repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/algum-repo-avulso
git config core.sshCommand &lt;span class="s2"&gt;"ssh -i ~/.ssh/id_ed25519_trabalho -F /dev/null"&lt;/span&gt;
git config user.email &lt;span class="s2"&gt;"joao@empresa.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Verificação final
&lt;/h2&gt;

&lt;p&gt;Dentro de cada repositório, confirme que o Git está usando o usuário e a chave corretos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projetos/trabalho/projeto-empresa
git config user.email
&lt;span class="c"&gt;# deve retornar: joao@empresa.com&lt;/span&gt;

git config core.sshCommand
&lt;span class="c"&gt;# deve retornar: ssh -i ~/.ssh/id_ed25519_trabalho -F /dev/null&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; ~/projetos/pessoal/meu-projeto
git config user.email
&lt;span class="c"&gt;# deve retornar: joao@gmail.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Resumo da estrutura
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.ssh/
├── id_ed25519_pessoal        ← chave privada pessoal
├── id_ed25519_pessoal.pub
├── id_ed25519_trabalho       ← chave privada do trabalho
└── id_ed25519_trabalho.pub

~/.gitconfig                  ← config global com includeIf
~/.gitconfig-pessoal          ← user, email e sshCommand pessoal
~/.gitconfig-trabalho         ← user, email e sshCommand do trabalho

~/projetos/
├── pessoal/                  ← clones pessoais aqui
└── trabalho/                 ← clones do trabalho aqui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Problemas comuns
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Still using the wrong email after setup"&lt;/strong&gt;&lt;br&gt;
Verifique se a barra final está no &lt;code&gt;includeIf&lt;/code&gt;. Rode &lt;code&gt;git config user.email&lt;/code&gt; dentro do repositório (não globalmente).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Permission denied (publickey)"&lt;/strong&gt;&lt;br&gt;
Rode &lt;code&gt;ssh -i ~/.ssh/id_ed25519_trabalho -vT git@gitlab.com&lt;/code&gt; para ver o que acontece. Confirme que a chave pública está cadastrada na conta correta no GitLab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"sshCommand não está sendo aplicado"&lt;/strong&gt;&lt;br&gt;
Confirme que o repositório está dentro da pasta mapeada no &lt;code&gt;includeIf&lt;/code&gt; e que a barra final está presente. Teste com &lt;code&gt;git config core.sshCommand&lt;/code&gt; dentro do repo.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Com essa configuração você nunca mais vai:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Commitar com o e-mail errado&lt;/li&gt;
&lt;li&gt;❌ Misturar credenciais de contas diferentes&lt;/li&gt;
&lt;li&gt;❌ Precisar criar aliases de host no &lt;code&gt;~/.ssh/config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;❌ Precisar configurar manualmente cada repositório&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A lógica é elegante: o &lt;strong&gt;&lt;code&gt;includeIf&lt;/code&gt;&lt;/strong&gt; do Git ativa automaticamente o &lt;code&gt;user&lt;/code&gt;, o &lt;code&gt;email&lt;/code&gt; e o &lt;code&gt;core.sshCommand&lt;/code&gt; certos com base na pasta — tudo em um único lugar, sem efeitos colaterais no restante do sistema.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Gostou? Deixa uma reação e compartilha com aquele dev que sempre commita com o e-mail errado 👇&lt;/em&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>ssh</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
