sql >> Databasteknik >  >> RDS >> PostgreSQL

Använder tvåfas commits på postgres

Jag tror att du har missförstått PREPARE TRANSACTION .

Det uttalandet avslutar arbetet med transaktionen, det vill säga det ska utfärdas efter allt arbete är gjort. Tanken är att PREPARE TRANSACTION gör allt som potentiellt skulle kunna misslyckas under en commit förutom själva commit. Det är för att garantera att en efterföljande COMMIT PREPARED kan inte misslyckas.

Tanken är att bearbetningen är som följer:

  • Kör START TRANSACTION på alla databaser som är involverade i den distribuerade transaktionen.

  • Gör allt arbete. Om det finns fel, ROLLBACK alla transaktioner.

  • Kör PREPARE TRANSACTION på alla databaser. Om det misslyckas någonstans, kör ROLLBACK PREPARED på de databaser där transaktionen redan var förberedd och ROLLBACK på de andra.

  • En gång PREPARE TRANSACTION har lyckats överallt, kör COMMIT PREPARED på alla inblandade databaser.

På så sätt kan du garantera "allt eller inget" över flera databaser.

En viktig komponent här som jag inte har nämnt är den distributerade transaktionshanteraren . Det är en mjukvara som ständigt memorerar var i ovanstående algoritm bearbetningen för närvarande är så att den kan städa upp eller fortsätta att utföra efter en krasch.

Utan en distribuerad transaktionshanterare är tvåfas commit inte värt mycket, och det är faktiskt farligt:​​om transaktioner fastnar i den "förberedda" fasen men inte är commiterade ännu, kommer de att fortsätta att hålla lås och (i fallet med PostgreSQL) blockerar autovakuumarbete även genom omstarter av servern , eftersom sådana transaktioner måste vara beständiga.

Detta är svårt att få rätt.




  1. Klona en post och använd sedan dess autoinkrement-id för ytterligare operationer

  2. Skillnader mellan utf8 och latin1

  3. Python+MySQL - Bulkinsert

  4. ElasticSearch PutMapping API:MapperParsingException Rottypmappning är inte tom efter analys