Naturalmente, quando se começa a estudar sobre desenvolvimento de software e a criar as primeiras aplicações, você logo começa a se deparar com o famoso banco de dados. À primeira vista, você entende que o banco de dados serve para guardar/agrupar as informações das suas aplicações e, na maioria das vezes, o primeiro contato sempre é com um banco SQL.
Nos primeiros usos, você vê que as coisas começam a fazer sentido, começa de fato a entender como as informações podem ser estruturadas e persistidas. É mágico!
Recentemente, comecei a me aprofundar mais sobre bancos de dados e suas particularidades, entendendo melhor seus conceitos, fundamentos e comportamentos. Nesse estudo, me deparei com um acrônimo interessante chamado ACID, que carrega características importantes para bancos de dados SQL.
Nesse post vamos falar um pouco sobre esse tal de ACID e entender como ele descreve algumas características importantes em transações de bancos de dados SQL.
A -> Atomicidade
Garante que operações feitas sejam atômicas. Por exemplo, modificações feitas em conjunto só devem ser concluídas em caso de sucesso de todas. Em outras palavras, a operação é tratada como indivisível.
Um exemplo simples é uma transferência entre duas contas:
Resultado de sucesso:
Conta A: -100
Conta B: +100
Transação confirmada.
Resultado 2, com falha:
Conta A: sem alteração
Conta B: sem alteração
Transação desfeita.
O resultado abaixo não deve acontecer:
Conta A: -100
Conta B: sem alteração
Não pode haver um estado parcialmente executado. A operação precisa acontecer por completo ou não acontecer.
Exemplo de SQL que garante atomicidade:
BEGIN;
UPDATE contas
SET saldo = saldo - 100
WHERE id = 1;
UPDATE contas
SET saldo = saldo + 100
WHERE id = 2;
COMMIT;
Caso algo dê errado, a transação pode ser desfeita:
BEGIN;
UPDATE contas
SET saldo = saldo - 100
WHERE id = 1;
UPDATE contas
SET saldo = saldo + 100
WHERE id = 2;
ROLLBACK;
Nesse caso, as alterações feitas dentro da transação não são persistidas.
C -> Consistência
A consistência é feita por meio de regras que são definidas nas estruturas do banco e que garantem que algumas operações respeitem o formato esperado dos dados.
Como, por exemplo: todo usuário precisa ter um e-mail único na tabela de users.
CREATE TABLE users (
email TEXT NOT NULL UNIQUE
);
Outro exemplo: todo usuário precisa ter um centro de custo válido atrelado.
CREATE TABLE users (
cost_center_id INT NOT NULL REFERENCES cost_centers(id)
);
Existem algumas restrições que garantem a consistência dos dados que serão armazenados.
Como:
PRIMARY KEYFOREIGN KEYNOT NULLUNIQUECHECK
Essas regras ajudam o banco a impedir que dados inválidos sejam gravados, mantendo o banco sempre em um estado consistente.
I -> Isolamento
Isolamento garante que uma transação não interfira de forma indevida em outra transação que esteja acontecendo ao mesmo tempo.
Em uma aplicação real, várias pessoas podem estar usando o sistema ao mesmo tempo. Com isso, podem existir várias operações acontecendo no banco simultaneamente. O isolamento define como o banco deve lidar com esse tipo de concorrência.
Imagine duas transações tentando alterar o saldo da mesma conta:
Transação 1: sacar R$ 100,00
Transação 2: sacar R$ 50,00
Se as duas transações lerem o mesmo saldo ao mesmo tempo e atualizarem a conta sem nenhum controle, uma operação pode acabar sobrescrevendo a outra ou trabalhando com um valor desatualizado.
O banco usa mecanismos como locks e níveis de isolamento para evitar esse tipo de problema.
Um exemplo em SQL:
BEGIN;
SELECT saldo
FROM contas
WHERE id = 1
FOR UPDATE;
UPDATE contas
SET saldo = saldo - 100
WHERE id = 1;
COMMIT;
Nesse caso, o FOR UPDATE indica que aquela linha será atualizada, então o banco pode bloquear outras transações que tentem modificar a mesma linha ao mesmo tempo.
Esse comportamento pode variar de acordo com o banco de dados e com o nível de isolamento configurado, mas a ideia principal é evitar que transações simultâneas gerem resultados inconsistentes.
D -> Durabilidade
Durabilidade garante que, depois que uma transação é confirmada, os dados realmente foram persistidos.
Ou seja, se o banco retornou sucesso depois de um COMMIT, espera-se que aquela informação continue existindo mesmo que ocorra alguma falha logo depois, como uma queda de energia ou reinicialização do servidor.
Exemplo:
BEGIN;
INSERT INTO pedidos (cliente_id, total)
VALUES (1, 250.00);
COMMIT;
Depois do COMMIT, esse pedido precisa continuar existindo no banco de dados.
Para garantir isso, os bancos usam alguns mecanismos internos, como logs de transação e estratégias de recuperação. A ideia é que, mesmo em caso de falha, o banco consiga recuperar as operações que já tinham sido confirmadas.
Na prática, a durabilidade é o que permite confiar que uma operação confirmada não vai simplesmente desaparecer.
Conclusão
ACID é um conceito muito importante quando começamos a entender bancos de dados além do uso básico de criar tabelas, inserir e buscar informações.
Recapitulando:
- Atomicidade: tudo acontece ou nada acontece.
- Consistência: as regras do banco continuam sendo respeitadas.
- Isolamento: transações simultâneas não interferem indevidamente umas nas outras.
- Durabilidade: depois do
COMMIT, os dados confirmados devem persistir.
No começo, parece só mais um termo técnico, mas ele ajuda bastante a entender como os bancos SQL lidam com transações e como eles conseguem manter os dados confiáveis mesmo com várias operações acontecendo ao mesmo tempo.
