To lock or not to lock?

Posted on: January 08, 2026 06:34 PM

Posted by: Renato

Categories: Laravel

Views: 182

To lock or not to lock? 🔒 Bloquear ou não bloquear?

🔒 Bloquear ou não bloquear?

Por quê?

Antes de tudo, precisamos entender por que precisamos de locking (bloqueio) no banco de dados, e nada melhor do que um cenário da vida real para isso.

Suponha que você seja assinante do meu conteúdo premium no Medium (não se preocupe, meu conteúdo é gratuito 😊) por US$ 5 por mês.

Vamos assumir que o Medium tenha um cronjob que cobra seu cartão por volta da meia-noite e, para efeito deste artigo, vamos supor que você tenha apenas US$ 5 no cartão (Deus me livre 😱).

Agora, como a boa coruja noturna 🦉 que você é, você está navegando pelo universo do Medium e encontra outra pessoa que escreve conteúdos legais sobre Angular —
 
Enea Jahollari (não se preocupe, o conteúdo dele também é gratuito).

Você então decide se inscrever também, por US$ 5.

E acontece que o exato momento em que você clica em “subscribe” é o mesmo momento em que o cronjob está processando a cobrança.

Quando dois ou mais clientes tentam atualizar o mesmo registro ao mesmo tempo, pode ocorrer um conflito conhecido como race condition (condição de corrida).

O cronjob lê o registro e vê que você tem US$ 5.
 Ao mesmo tempo, quando você clica em “subscribe”, o sistema também lê o registro e vê que você tem US$ 5.

Ambos seguem adiante e atualizam a coluna amount (claro, o Medium é muito mais sofisticado do que isso), e dessa forma acabamos com um valor inconsistente no banco.

🧠 Duas abordagens para concorrência em banco de dados

Existem duas abordagens principais para lidar com acesso e modificação concorrente de dados em um banco de dados.

🔐 Pessimistic Locking (Bloqueio Pessimista)

O pessimistic locking, também conhecido como pessimistic concurrency control, é um mecanismo que assume que conflitos vão acontecer e, por isso, adota uma abordagem cautelosa.

Ao usar esse tipo de bloqueio, você bloqueia explicitamente um registro (ou conjunto de registros) ao acessá-lo, impedindo que outros processos ou threads o modifiquem até que o lock seja liberado.

Essa abordagem é útil quando:

  • Conflitos são prováveis

  • Você precisa garantir acesso exclusivo aos dados

🔓 Optimistic Locking (Bloqueio Otimista)

O optimistic locking, também conhecido como optimistic concurrency control, adota uma abordagem mais confiante e assume que conflitos são raros.

Nesse modelo:

  • Os registros não são bloqueados durante a leitura

  • Usa-se um campo de versão ou timestamp para detectar conflitos no momento da escrita

Ao atualizar um registro, você compara a versão (ou timestamp) atual com a que foi lida inicialmente.
 Se forem diferentes, significa que
alguém alterou o registro nesse meio tempo, e o conflito pode ser tratado adequadamente.

⚙️ Como usar isso no Laravel?

🔒 Pessimistic Locking no Laravel

No Laravel, você pode usar bloqueio pessimista chamando o método lockForUpdate() no Query Builder antes de buscar ou modificar os registros.

Exemplo:

$user = User::where('id', $userId)

    ->lockForUpdate()

    ->first();

 

O método lockForUpdate() adiciona a cláusula FOR UPDATE à query SQL, bloqueando as linhas selecionadas até que:

  • A transação seja finalizada, ou

  • O lock seja liberado

🔓 Optimistic Locking no Laravel

O Laravel suporta optimistic locking através do uso de timestamps.

Por padrão, o Laravel adiciona as colunas:

  • created_at

  • updated_at

Essas colunas podem ser usadas para detectar concorrência.

Quando você atualiza um registro, o Laravel verifica automaticamente se o valor de updated_at mudou desde que o registro foi carregado.
 Se tiver mudado, uma exceção
Illuminate\Database\Eloquent\ModelNotFoundException será lançada, indicando um conflito.

🖼️ Transcrição da imagem anexada

<?php

 

DB::transaction(function () use ($id, $charge) {

    $currentAmount = DB::table('users')

        ->where('id', $id)

        ->lockForUpdate()

        ->first('amount');

 

    DB::table('users')

        ->where('id', $id)

        ->update(['amount' => ($currentAmount - $charge)]);

 

    return true;

}, 3);

 

📌 Explicação do código

  • Linha 4: Primeiro, lemos o saldo atual do usuário que será debitado.

  • Linha 6: Aplicamos o lockForUpdate(), garantindo que nenhum outro processo consiga modificar esse registro até que o lock seja liberado.

  • Linha 9: Atualizamos o saldo do usuário subtraindo o valor cobrado.

  • Linha 15: Utilizamos DB::transaction() com 3 tentativas, uma boa prática para evitar deadlocks.

⚠️ Nota importante

Para usar transactions no MySQL, é necessário que o banco esteja usando o engine InnoDB.

📣 Fique à vontade para se inscrever, bater palmas 👏🏻, comentar 💬 e compartilhar este artigo com quem quiser.

Como sempre, agradeço muito o seu apoio.
 Obrigado pela leitura! 🙌

 

Exemplo:

// The Laravel query builder includes a `lockForUpdate()` function.

// This stops any updates or another shared lock on selected record

// until the transaction is finalized.

 

DB::transaction(function() {

    $user = User::lockForUpdate()->find(1);

});

 

// There is also sharedLock() function that only prevents updates on

// the selected record but permits selecting the record with another lock.

 

DB::transaction(function() {

    $user = User::sharedLock()->find(1);

});

 

// For more tips 👉 @justsanjit 👈

 

💡 Analogia rápida para fixar:
 Pense no banco de dados como um
arquivo físico em um escritório:

  • lockForUpdate() é como trancar o arquivo na sua mesa: ninguém mais pode mexer até você terminar.

  • sharedLock() é como deixar o arquivo em uma mesa de leitura: várias pessoas podem ler, mas ninguém pode alterar enquanto ele está ali.

Fonte: https://medium.com/@erlandmuchasaj/to-lock-or-not-to-lock-974afdfe0b02

O método lockForUpdate() é uma funcionalidade clássica do Laravel para lidar com concorrência no banco de dados (Pessimistic Locking).

Ele foi implementado originalmente no Laravel 4.0, lançado em maio de 2013.

Desde então, ele permanece como uma ferramenta essencial para garantir que uma linha do banco de dados não seja alterada por outro processo enquanto a sua transação atual a estiver processando.

Dica importante: O suporte para esses locks depende do seu motor de banco de dados. No MySQL, por exemplo, você precisa estar usando o motor InnoDB, pois o MyISAM não suporta locks de linha, apenas de tabela inteira.


4

Share

Donate to Site


About Author

Renato

Developer

Add a Comment
Comments 1 Comments
  • Rlucena
    Rlucena - há 4 meses
    O método lockForUpdate() é uma funcionalidade clássica do Laravel para lidar com concorrência no banco de dados (Pessimistic Locking). Ele foi implementado originalmente no Laravel 4.0, lançado em maio de 2013. Desde então, ele permanece como uma ferramenta essencial para garantir que uma linha do banco de dados não seja alterada por outro processo enquanto a sua transação atual a estiver processando. Dica importante: O suporte para esses locks depende do seu motor de banco de dados. No MySQL, por exemplo, você precisa estar usando o motor InnoDB, pois o MyISAM não suporta locks de linha, apenas de tabela inteira.

Blog Search


Categories

Laravel (227) PHP (151) linux (124) Variados (110) ubuntu (58) Dicas (58) developer (48) postgresql (45) database (44) sql (42) Docker (32) mysql (31) front-end (31) devops (26) webdev (24) programming (23) tecnologia (19) eloquent (19) aws (19) dba (18) backend (16) OUTROS (17) laravelphp (16) debian (12) dev (12) git (10) react (10) reactjs (10) 100DaysOfCode (10) PHP Swoole (9) node (9) javascript (9) nginx (9) inteligencia-artificial (9) linux-tools (8) Architecture (8) ciencia (7) github (7) vue (7) vim (6) jwt (6) arquitetura (6) windows (6) api (6) vscode (6) nodejs (6) webservice (6) DevSecOps (5) apache (5) macox (5) s3 (5) servers (5) ia (5) authentication (5) rest (5) reactnative (5) angularjs (4) inteligenciadedados (4) Padrao de design (4) artigo (4) wsl (4) Swoole (4) lets-encrypt (4) query (4) Raspberry (4) openai (4) google (4) npm (4) opensource (4) mariadb (4) jenkins (4) Kubernetes (4) gitlab (4) angular (4) autenticacao (4) shell (4) mongodb (4) macos (3) web (2) jobs (3) websocket (3) ssh (3) bash (3) hardware (3) tests (3) db (3) politica (3) intel (3) CMS (2) sail (3) script (3) performance (3) js (3) mysqli (3) Black Hat (3) RabbitMQ (3) educacao (3) mac (3) fedora (3) containers (3) json (3) authorization (3) phpswoole (3) ddd (3) blade (3) terminal (3) log (3) redis (2) claude (2) ArchLinux (2) java (2) saude (1) seguranca (2) auth (2) cron (2) phpunit (2) kube (2) multiple_authen (2) policia (2) neovim (2) golang (2) noticias (2) livros (2) Transcribe (2) ElonMusk (2) imagick (2) maps (2) colors (2) Passport (2) JQuery (2) phpfpm (2) autorizacao (2) monitoring (2) laptop (2) gnome (2) powerbi (2) telefonia (2) nvm (2) unix (2) magento (2) iot (2) ffmpeg (2) combustivel (2) webhook (2) microservices (2) Curisidades (2) Solid (2) zsh (2) Go (2) BigLinux (2) POO (2) LazyVim (2) gource (2) Python (2) Oauth2 (2) android (2) openswoole (2) artificialintelligence (2) security (2) bancodedados (2) tailwind (2) homeOffice (2) html (2) chatgpt (1) idiomas (1) eventdrive (1) uuid (1) restfull (1) aplicativo (1) optimization (1) mapas (1) Fetch (1) collections (1) RustLang (1) matematica (1) Filament (1) compactar (1) paypal (1) microg (1) forcas armadas (1) militar (1) fullsta (1) smartphones (1) automacao (1) Monitor (1) zend (1) spaceship (1) PKCE (1) l2tp (1) Glacier (1) laraveloctane (1) Deus (1) binaural (1) gpt (1) bolsonaro (1) privacidade (1) linkedin (1) documentation (1) brain (1) adb (1) nvidia (1) host (1) ecommerce (1) c4-models (1) altadisponibilidade (1) octane (1) lucena (1) http (1) TypeScript (1) replication (1) faceapp (1) vala (1) cloudstack (1) rpi (1) apple (1) oracle (1) iode (1) ffaa (1) vpn (1) MeioAmbiente (1) firefox (1) composer (1) scheduling (1) Asahi (1) pendrive (1) microservice (1) front (1) cor (1) auth (1) modelagemdedados (1) k8s (1) gasolina (1) wsl2 (1) csv (1) soap (1) piada (1) KubeCon (1) zorin-os (1) spring-boot (1) backup (1) playwright (1) Deepin (1) storage (1) benchmark (1) networking (1) Swoole (1) biologia (1) node-red (1) LETSENCRYPT (1) Grunt (1) Diagramas (1) boot (1) haru (1) dracula (1) TrabalhoEmEquipe (1) Brasil (1) queue (1) agi (1) llama (1) hotfix (1) economia (1) transcription (1) cache (1) Amazon (1) October (1) lumen (1) Hyperf (1) m1 (1) Error (1) cinnamon (1) repmgr (1) federal (1) ruby (1) AppSec (1) orm (1) ArquiteturaDeSoftware (1) Passwordless (1) memcached (1) flow (1) compression (1) athena (1) front (1) wine (1) covid19 (0) services (1) phpjasper (1) models (1) kali-linux (1) geojson (1) yarn (1) picpay (1) Monolith (1) banco (1) PNPM (1) Desenvolvedor (1) Structurizr (1) symfony (1) presenter (1) lider (1) guard (1) tensorflow (1) bootstrap (1) nuance (1) historia (1) dropbox (1) traefik (1) bug (1) akitando (1) llm (1) htm (1) transformers (1) cavalotroia (1) odd (1) Oh My Zsh (1) ibm (1) escopos (1) usb (1) ckeditor (1) API_KEY_GOOGLE_MAPS (1) Manjaro (1) vicuna (1) coding (1) rust (1) markdown (1) JasperReports (1) Fibonacci (1) community (1) Samurai (1) payment (1) messaging (1) Jesus (1) flutter (1) Migration (1) workflow (1) cqrs (1) kitematic (1) geospacial (1) yeshua (1) data (1) sonarqube (1) Axios (1) pipelines (1) Mozilla (1) kvm (1) GitOps (1) sqlite (1) podcast (1) n8n (1) LaravelFilament (1) God (1) DesenvolvimentoProfissional (1) sw (1) bigtech (1) postgres (1) NoCookies (1) LeetCode (1) governancadedados (1) prf (1) nosql (1) Lideranca (1) Hackers (1) Bots (1) pytorch (1) nuxt (1) liquid (1) ec2 (1) transaction (1) c4 (1) rancher (1) algoritimo (1) Observability (1) Elasticsearch (1) translate (1) certbot (1) OOD (0) controllers (0)

New Articles



Get Latest Updates by Email