sql >> Databasteknik >  >> RDS >> PostgreSQL

Autorollback i postgres med PDO

Det är inte PDO:s fel, det är inneboende i PostgreSQL:s transaktionshantering. Se:

PostgreSQL rullar inte transaktionen tillbaka, men den sätter den till ett avbrutet tillstånd där det bara kan rulla tillbaka, och där alla uttalanden utom ROLLBACK rapportera ett fel:

(Jag är förvånad över att inte hitta detta hänvisat till i den officiella dokumentationen; tror att jag måste skriva en korrigeringsfil för att förbättra det.)

Så. När du försöker/fånga och svälja undantaget i PDO, fångar du ett undantag på PHP-sidan, men du ändrar inte det faktum att PostgreSQL-transaktionen är i ett avbrutet tillstånd.

Om du ville kunna svälja undantag och fortsätta använda transaktionen måste du skapa en SAVEPOINT före varje påstående som kan misslyckas. Om det misslyckas måste du ROLLBACK TO SAVEPOINT ...; . Om det lyckas kan du RELEASE SAVEPOINT ...; . Detta medför extra overhead på databasen för transaktionshantering, lägger till rundresor och bränner igenom transaktions-ID snabbare (vilket innebär att PostgreSQL måste göra mer bakgrundsrensningsarbete).

Det är i allmänhet att föredra att istället designa din SQL så att den inte misslyckas under normala omständigheter. Till exempel kan du validera de flesta begränsningar på klientsidan, behandla begränsningarna på serversidan som en andra säkerhetsnivå samtidigt som du fångar de flesta fel på klientsidan.

Om det är opraktiskt, gör din applikation feltolerant, så att den kan försöka igen en misslyckad transaktion. Ibland är detta ändå nödvändigt - till exempel kan du i allmänhet inte använda räddningspunkter för att återhämta dig från dödlägestransaktionsavbrott eller serialiseringsfel. Det kan också vara användbart att hålla felbenägna transaktioner så korta som möjligt, göra bara det minsta arbete som krävs, så att du har mindre att hålla reda på och upprepa.

Så:Om möjligt, istället för att svälja ett undantag, kör felbenägen databaskod i en återförsöksslinga. Se till att din kod sparar informationen den behöver för att försöka göra om hela transaktionen vid fel, inte bara det senaste uttalandet.

Kom ihåg, alla transaktionen kan misslyckas:DBA kan starta om databasen för att applicera en patch, systemet kan få slut på RAM på grund av ett skenande cron-jobb, etc. Så misslyckande appar är en bra design i alla fall.

Rekvisita till dig för att åtminstone använda PDO-undantag och hantera undantag - du är redan långt före de flesta utvecklare.




  1. SQL-fråga för att få avtalslista

  2. org.hibernate.HibernateException:Databasen returnerade inget naturligt genererat identitetsvärde

  3. MySQL - Hur man normaliserar kolumn som innehåller avgränsningsseparerade ID:n

  4. Autentiseringsplugin 'caching_sha2_password' stöds inte