Sobre transações
Trabalhei algum tempo em projetos usando bancos de dados relacionais, lembro que
era muito conveniente poder usar transações nesses sistemas. Bastava um,
BEGIN TRANSACTION
e eu não precisava me preocupar mais com a consistencia dos
dados, tudo funcionava como esperado. Ou deveria…
Lembro de ter alguns casos que eu não sabia o por quê de alguns dados estarem inconsistentes, por isso comecei a pesquisar sobre o tema, até que cheguei na seguinte palestra:
Nesta, @aphyr apresenta alguns sistemas e seus modos de falhas, comentando casos estranhos sobre esses sistemas e como a documentação dos mesmos não condiz necessariamente com a realidade. Isso foi um alerta, provavelmente não tinha me aprofundado sobre o funcionamento do banco e acabei assumindo um comportamento ideal. Procurei outras referências sobre o assunto e me deparei com a seguinte palestra:
Essa palestra é genial! @martinkl explica de maneira didática como transações funcionam nos bancos de dados, começando pelas propriedades das transações, ou mais conhecido como ACID.
Ele começa explicando como o conceito de Durability mudou com o passar do tempo, sendo primeiramente interpretado como salvar os dados em fita, depois salvar os dados em disco, para, atualmente, ter os dados replicados em mais de um local.
Seguindo com o conceito de Consistency, que por muitas vezes é confundido com Atomic Consistency do teorema CAP, e está mais relacionado com como as aplicações usam os bancos de dados do que com o banco propriamente dito.
O próximo tópico que ele aborda brevemente é o da Atomicity, o qual é frequentemente confundido com Isolation. Ele deixa claro que Atomicity está relacionado ao modo de falha da transação, sendo que, caso ela falhe, o estado do banco não deve mudar.
Sobre Atomicity, é interessante entender que essa característica da transação já cobre uma série de problemas como crash, falha de energia, falha de rede, deadlock e falha condicional, todas essa família de problemas já está tratada por essa característica da transação.
Depois de passar por quase todo o acrônimo, ele se aprofunda no tema de isolação das transações, que está muito relacionado a concorrência e como isso é tratado nos bancos. Você pode ter os seguintes níveis de isolamento:
- Serializable: Melhor nível de isolamento
- Snapshot Isolation
- Read Committed: Default no PostgresSQL
- Read Uncommitted: Pior nível de isolamento, a.k.a
¯\_(ツ)_/¯
Ele também ilustra cada um problemas de concorrência que podem afetar cada nível de isolação:
Problema | Read Uncommitted | Read Committed | Snapshot Isolation | Serializable |
Dirty reads | [x] | [ ] | [ ] | [ ] |
Dirty writes | [x] | [ ] | [ ] | [ ] |
Read skew | [x] | [x] | [ ] | [ ] |
Write skew | [x] | [x] | [x] | [ ] |
Visto tudo isso, eu entendi que o buraco que eu estava me metendo era bem maior que imaginava, e que era uma boa alterar o a configuração padrão do PostgresSQL, para evitar os aqueles problemas.
Esse rabbit hole de transações, sistemas distribuídos e concorrência é muito divertido seguir, mas fica confuso muito rápido. Ainda mais quando não se tem contato direto com o tema.
Material extra
- An introduction to distributed systems escrito pelo @aphyr