Tecnologia / Artigos / O Guia Definitivo do Design de Software /
Transação não é isolamento

Cléber

![isolation-in-mountains.jpg](/files/160) *Photo by [Pablo García Saldaña](https://unsplash.com/@garciasaldana_) on [Unsplash](https://unsplash.com/s/photos/isolation)* --- Pelo menos uma vez na minha vida eu participei de uma discussão a respeito de por que, afinal, determinada operação no banco de dados, quando executada ao mesmo tempo que outra, era influenciada por esta, sendo que ambas "eram transações". Coube a mim a árdua tarefa de explicar para a turma que **transação não é sinônimo de isolamento**. E o conceito todo pode ser um pouco complicado de se entender, porque as transações em um banco de dados relacional (usarei o Postgres como exemplo) **provém** um determinado nível, sim, de isolamento. Mas isso não significa que "envelopar" um conjunto de comandos em uma transação fará com que, magicamente, estes comandos sejam executados, do começo ao fim, como se o estado do banco de dados à volta nunca mudasse. # O nível padrão de isolamento *Read Committed is the default isolation level in PostgreSQL. When a transaction uses this isolation level, a SELECT query (without a FOR UPDATE/SHARE clause) sees only data committed before the query began; it never sees either uncommitted data or changes committed during query execution by concurrent transactions. In effect, a SELECT query sees a snapshot of the database as of the instant the query begins to run. However, SELECT does see the effects of previous updates executed within its own transaction, even though they are not yet committed. Also note that two successive SELECT commands can see different data, even though they are within a single transaction, if other transactions commit changes after the first SELECT starts and before the second SELECT starts.* Fonte: [https://www.postgresql.org/docs/9.5/transaction-iso.html](https://www.postgresql.org/docs/9.5/transaction-iso.html) Repare que a "*visibilidade dos dados commitados*" aplica-se sempre **ao SELECT, e não à transação em si**. Ou seja: se sua *transaction* contém 25 comandos *SELECT*, **nada impede** que os dados das tabelas em questão mudem entre cada comando. ## Exemplo (Repare que uso **pseudo-código**. Ignore pequenos detalhes e tente simplesmente entender por alto o que acontece.) | **[Transaction 1]** | **[Transaction 2]** | **[produto(id=1).qtde]** | | -------- | -------- | -------- | | | `Começa a transação` | 20 | | | (Operação 1) | 20 | | `Começa a transação` | (Operação 2) | 20 | | (Operação 1) | (Operação 3) | 20 | | (Operação 2) | `UPDATE produto.qtde+=30 WHERE id=1` | 20 | | (Operação 3) | `Fim da transação` | 50 | | `UPDATE produto.qtde+=30 WHERE id=1` | | 50 | | `Fim da transação` | | 80 | Qualquer serviço que trate mensagens sem garantia de entrega-apenas-uma-vez ou simplesmente com algum tipo de concorrência e com *queries* razoavelmente complexas pode acabar numa situação dessas. Duvida? Pois bem, novamente citarei o manual: *UPDATE, DELETE, SELECT FOR UPDATE, and SELECT FOR SHARE commands behave the same as SELECT in terms of searching for target rows: they will only find target rows that were committed as of the command start time. However, such a target row might have already been updated (or deleted or locked) by another concurrent transaction by the time it is found. In this case, the would-be updater will wait for the first updating transaction to commit or roll back (if it is still in progress). [...]. If the first updater commits, [...] it will attempt to apply its operation to the updated version of the row.* Fonte: [https://www.postgresql.org/docs/9.5/transaction-iso.html](https://www.postgresql.org/docs/9.5/transaction-iso.html) Há um breve consolo no fato de que o `WHERE` é "atualizado" quando uma transação concorrente termina, mas nem sempre nossas consultas podem ser "salvas" pelos `WHERE`. # Conhecimento é poder Não é complicado criar *queries* que comportem-se corretamente em situações de concorrência, contanto que você **conheça** o comportamento que o seu SGBD lhe entrega. Mas se você acredita que `START TRANSACTION` fará qualquer coisa além do que realmente faz, logo começarão a surgir problemas "inexplicáveis" -- que o forçarão, veja só, a finalmente ler a documentação e entender como as coisas funcionam... # Resumo * Transações dão **algum** isolamento, mas não "total isolamento".

Curti

37 visitantes curtiram esse Item.

Anterior: Teste tudo | Próximo: Fale inglês, não latim