PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Usando commits de duas fases no postgres


Acho que você não entendeu PREPARE TRANSACTION .

Essa instrução encerra o trabalho na transação, ou seja, deve ser emitida depois todo o trabalho é feito. A ideia é que PREPARE TRANSACTION faz tudo o que poderia falhar durante um commit, exceto o commit em si. Isso é para garantir que um COMMIT PREPARED subsequente não pode falhar.

A ideia é que o processamento seja o seguinte:

  • Execute START TRANSACTION em todos os bancos de dados envolvidos na transação distribuída.

  • Faça todo o trabalho. Se houver erros, ROLLBACK todas as transacções.

  • Execute PREPARE TRANSACTION em todos os bancos de dados. Se isso falhar em qualquer lugar, execute ROLLBACK PREPARED naqueles bancos de dados onde a transação já foi preparada e ROLLBACK sobre os outros.

  • Uma vez PREPARE TRANSACTION teve sucesso em todos os lugares, execute COMMIT PREPARED em todos os bancos de dados envolvidos.

Dessa forma, você pode garantir “tudo ou nada” em vários bancos de dados.

Um componente importante aqui que não mencionei é o gerenciador de transações distribuídas . É um software que memoriza persistentemente onde o processamento do algoritmo acima está atualmente para que ele possa limpar ou continuar confirmando após uma falha.

Sem um gerenciador de transações distribuído, o commit de duas fases não vale muito e é realmente perigoso:se as transações ficarem presas na fase “preparada”, mas ainda não forem confirmadas, elas continuarão mantendo bloqueios e (no caso de PostgreSQL) bloqueia o trabalho de autovacuum mesmo através de reinicializações do servidor , pois essas transações precisam ser persistentes.

Isso é difícil de acertar.