O PostgreSQL vem com recursos sólidos e testados ao longo do tempo que permitem definir exatamente o que deve acontecer quando vários clientes tentam atualizar os mesmos dados simultaneamente. Um deles é o nível de isolamento das transações.
Continue lendo para saber mais sobre como o isolamento de transações funciona no PostgreSQL.
Transações e nível de isolamento
As transações são a maneira fundamental de alterar dados em um RDBMS. Os RDBMS modernos permitem que mais de uma transação seja executada simultaneamente e, consequentemente, vêm com uma variedade de ferramentas – algumas padrão, outras específicas de RDBMS – para desenvolvedores de aplicativos especificarem como suas transações devem ou não interagir com outras transações.
Níveis de isolamento de transações e bloqueios pessimistas são duas dessas ferramentas. Embora sejam necessários para a integridade e o desempenho dos dados, infelizmente não são intuitivos para entender ou usar.
O nível de isolamento de uma transação, no PostgreSQL, pode ser um dos seguintes:
- Ler Comprometido
- Leitura repetível
- Serializável
Cada transação tem seu nível de isolamento definido para um desses quando é criada. O nível padrão é “leitura confirmada”.
Observe que o padrão SQL também define “read uncommitted”, que não é suportado no Postgres. Você tem que usar o nível mais próximo e mais alto de “leitura confirmada”.
Vamos ver o que esses níveis significam.
Ler confirmado
O que acontece quando uma transação (não finalizada) insere linhas em uma tabela e a outra transação (também não finalizada) tenta ler todas as linhas da tabela? Se a segunda transação é capaz de ver as linhas inseridas pela primeira, então essa leitura é chamada de leitura suja – porque a primeira transação pode reverter e a segunda transação teria lido linhas “fantasmas” que nunca existiram.
A leitura confirmada O nível de isolamento garante que leituras sujas nunca acontecerão. Aqui está um exemplo:
Como você pode ver, a segunda transação não pôde ler os dados da primeira transação como ainda não confirmados.
Leitura repetível
Ainda outro problema é o de leituras não repetíveis. Isso acontece quando uma transação lê uma linha e a lê novamente um pouco mais tarde, mas obtém um resultado diferente - porque a linha foi atualizada no meio por outra transação. A leitura tornou-se não repetível , como mostrado neste exemplo:
Para corrigir esse problema, defina o nível de isolamento da transação como “repeatableread”. O PostgreSQL então garantirá que a segunda (ou qualquer) leitura também retornará o mesmo resultado da primeira leitura. Aqui está o mesmo cenário no nível de isolamento atualizado:
Observe que o nível de isolamento foi especificado junto com a instrução BEGIN. Tambémépossível especificar isso no nível de conexão (como um parâmetro de conexão), como um parâmetro de configuração (
default_transaction_isolation
) e usando a instrução SET TRANSACTION. Serializável
O próximo nível de isolamento aborda o problema de atualizações perdidas . As atualizações realizadas em uma transação podem ser “perdidas” ou substituídas por outra transação que é executada simultaneamente, conforme mostrado aqui:
Aqui o UPDATE da segunda transação bloqueia, pois o PostgreSQL coloca um bloqueio para evitar outra atualização até que a primeira transação seja concluída. No entanto, a alteração da primeira transação é perdida, porque a segunda “substituiu” a linha.
Se esse tipo de comportamento não for aceitável, você pode atualizar o nível de isolamento para serializável:
Nesse nível, a confirmação da segunda transação falha. As ações da segunda transação foram baseadas em fatos que foram invalidados no momento em que estava prestes a ser confirmada.
Embora a serialização forneça o mais alto nível de segurança, isso também significa que o aplicativo precisa detectar essas falhas de confirmação e tentar novamente toda a transação.