# ACID

Em ciência da computação, ACID (acrônimo de Atomicidade, Consistência, Isolamento e Durabilidade - do inglês: Atomicity, Consistency, Isolation, Durability) é um conjunto de propriedades de transação em banco de dados.
No contexto de banco de dados, transação é uma sequência de operações de banco de dados que satisfaz as propriedades ACID e, portanto, pode ser percebida como uma operação lógica única sobre os dados. Por exemplo, uma transferência de fundos de uma conta bancária para outra, mesmo envolvendo múltiplas mudanças, como debitar uma conta e creditar outra, é uma transação única.
Em 1983, Andreas Reuter e Theo Härder inventaram o acrônimo ACID com base em trabalhos anteriores pelo cientista da computação Jim Gray que enumerou Atomicidade, Consistência e Durabilidade, mas deixou de fora o Isolamento ao caracterizar o conceito de transação. Essas quatro propriedades descrevem as principais garantias do paradigma de transação, que influenciou muitos aspectos do desenvolvimento em sistemas de banco de dados.
De acordo com Gray e Reuter, o IMS suportou as transações ACID em 1973 (embora o termo ACID tenha chegado depois).

## Características

As características dessas quatro propriedades conforme definido por Reuter e Härder são as seguintes:

### Atomicidade

Trata o trabalho como parte indivisível (atômico). A transação deve ter todas as suas operações executadas em caso de sucesso ou, em caso de falha, nenhum resultado de alguma operação refletido sobre a base de dados. Ou seja, após o término de uma transação (commit ou rollback), a base de dados não deve refletir resultados parciais da transação.
Exemplo: Em uma transferência de valores entre contas bancárias, é necessário que, da conta origem seja retirado um valor X e na conta destino seja somado o mesmo valor X. As duas operações devem ser completadas sem que qualquer erro aconteça. Em caso de algum erro, todas as alterações feitas nessa operação de transferência devem ser desfeitas.
Em projeto de banco de dados relacional, atomicidade também se refere à Primeira Forma Normal, na qual uma relação não pode conter atributos multi valorados, ou seja, o domínio de um atributo deve conter apenas valores atômicos.

### Consistência

A execução de uma transação deve levar o banco de dados de um estado consistente a um outro estado consistente, ou seja, uma transação deve respeitar as regras de integridade dos dados (como unicidade de chaves, restrições de integridade lógica, etc.).
Todos os dados escritos no banco de dados devem ser válidos de acordo com todas as regras definidas, incluindo restrições (constraints), operações em cascata (cascade), triggers e qualquer combinação destes. Isso não garante a correção da transação de todas as maneiras que o programador de aplicativos pode ter desejado (que é responsabilidade do código no nível do aplicativo), mas sim que qualquer erro de programação não pode resultar na violação de regras definidas.
Por exemplo, considere um banco de dados que guarde informações de clientes e que use o CPF (equivalente ao NIF em Portugal) como chave primária. Então, qualquer inserção ou alteração no banco não pode duplicar um CPF (unicidade de chaves) ou colocar um valor de CPF inválido, como o valor 000.000.000-00 (restrição de integridade lógica).

### Isolamento

Em sistemas multi usuários, várias transações podem acessar simultaneamente o mesmo registro (ou parte do registro) no banco de dados. Por exemplo, no mesmo instante é possível que um usuário tente alterar um registro e outro usuário esteja tentando ler este mesmo registro.
O isolamento é um conjunto de técnicas que tentam evitar que transações paralelas interfiram umas nas outras, fazendo com que o resultado de várias transações em paralelo seja o mesmo resultado se as mesmas transações fossem executadas sequencialmente (uma após a outra). Operações exteriores a uma dada transação jamais verão esta transação em estados intermediários.
Fornecer isolamento é o objetivo principal do controle de concorrência. Dependendo do método de controle de concorrência (ou seja, se ele usa uma serialização rígida strict -- em oposição a relaxed --), os efeitos de uma transação incompleta podem não ser visíveis para outra transação.
Por exemplo, considere as duas seguintes transações efetuadas em um banco de dados com informações de funcionários de uma empresa:
$T_{1}$: Dar um bônus de 100 reais para o empregado portador do CPF 490.120.530-30, que tem um salário de 1000 reais.
$T_{2}$: Dar um bônus de 10% reais para o mesmo empregado (CPF 490.120.530-30, salário de 1000 reais).
Digamos que elas tenham a seguinte forma:
$T_{1}$:
* seleciona funcionário que tenha CPF igual à 490.120.530-30;
* altera o salário somando 100 reais;
* faz o commit (confirma a gravação no banco de dados).
$T_{2}$:
* seleciona funcionário que tenha CPF igual à 490.120.530-30;
* altera o salário somando 10%;
* faz o commit (confirma a gravação no banco de dados).
Se as duas transações forem executadas sequencialmente, os salário deste funcionário poderá ser:
$T_{1}$ e depois $T_{2}$: salário passa a ser 1100 reais e depois, somando 10% de 1100, passa a ser 1210 reais.
$T_{2}$ e depois $T_{1}$: salário passa a ser 1100 reais e depois, somando 100 reais, passa a ser 1200 reais.
Então, se executarmos estas duas transações em paralelo, o valor final do salário deste funcionário deve ser de 1200 ou de 1210 reais.
Se as duas transações não estiverem isoladas (uma puder ver os resultados parciais da outra), então, quando executadas em paralelo, pode ocorrer o seguinte:
* $T_{1}$ seleciona o funcionário;
* $T_{2}$ seleciona o mesmo funcionário;
* $T_{1}$ altera o salário para 1100 reais;
* $T_{2}$ altera também o salário para 1100 reais;
* $T_{1}$ grava a mudança no banco de dados;
* $T_{2}$ também grava a mudança no banco de dados.
Assim, no fim, o salário deste funcionário será igual à 1100 reais (valor gravado por $T_{2}$). Isto ocorreu neste exemplo porque deixamos as duas transações alterarem o mesmo campo (o salário) ao mesmo tempo. A propriedade de isolamento não permite que isto ocorra.
Algumas técnicas de isolamento conhecidas são os bloqueios bifásicos e ordenação de marcas de tempo.

### Durabilidade

Os efeitos de uma transação em caso de sucesso (commit) devem persistir no banco de dados mesmo em casos de quedas de energia, travamentos ou erros. Garante que os dados estarão disponíveis em definitivo. Em um banco de dados relacional, por exemplo, quando um grupo de instruções SQL é executado, os resultados precisam ser armazenados permanentemente (mesmo que o banco de dados falhe imediatamente depois). Para se defender contra a perda de energia, as transações (ou seus efeitos) devem ser registradas em uma memória não volátil.