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:
-
ExecuteSTART 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.
-
ExecutePREPARE TRANSACTION
em todos os bancos de dados. Se isso falhar em qualquer lugar, executeROLLBACK PREPARED
naqueles bancos de dados onde a transação já foi preparada eROLLBACK
sobre os outros.
-
Uma vezPREPARE TRANSACTION
teve sucesso em todos os lugares, executeCOMMIT 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.