sql >> Base de Datos >  >> RDS >> PostgreSQL

Usando confirmaciones de dos fases en postgres

Creo que entendiste mal PREPARE TRANSACTION .

Esa declaración finaliza el trabajo en la transacción, es decir, debe emitirse después Todo el trabajo está hecho. La idea es que PREPARE TRANSACTION hace todo lo que podría fallar potencialmente durante una confirmación, excepto la confirmación en sí. Eso es para garantizar que un COMMIT PREPARED posterior no puede fallar.

La idea es que el procesamiento sea el siguiente:

  • Ejecute START TRANSACTION en todas las bases de datos involucradas en la transacción distribuida.

  • Haz todo el trabajo. Si hay errores, ROLLBACK todas las transacciones.

  • Ejecute PREPARE TRANSACTION en todas las bases de datos. Si eso falla en alguna parte, ejecute ROLLBACK PREPARED en aquellas bases de datos donde la transacción ya fue preparada y ROLLBACK en los demás.

  • Una vez PREPARE TRANSACTION ha tenido éxito en todas partes, ejecute COMMIT PREPARED en todas las bases de datos involucradas.

De esa manera, puede garantizar "todo o nada" en varias bases de datos.

Un componente importante aquí que no he mencionado es el administrador de transacciones distribuidas . Es una pieza de software que memoriza persistentemente en qué parte del procesamiento del algoritmo anterior se encuentra actualmente para que pueda limpiar o continuar con la confirmación después de un bloqueo.

Sin un administrador de transacciones distribuidas, la confirmación en dos fases no vale mucho y, de hecho, es peligrosa:si las transacciones se atascan en la fase "preparada" pero aún no están confirmadas, seguirán reteniendo bloqueos y (en el caso de PostgreSQL) bloquea el trabajo de vacío automático incluso a través de reinicios del servidor , ya que tales transacciones deben ser persistentes.

Esto es difícil de hacer bien.