April 26, 2006

PostgreSQL | How to ensure you're in a transaction

Transactions are only useful when you actually use them, otherwise it's too late when you realize you've forgotten the WHERE clause and would really, really like to be able to roll back the changes - as Robert Treat found out recently.

If you're lucky conventional backups or PITR will help you avoid total disaster, but apart from the delay in extracting the necessary data from the backups and reading it in, Murphy's Law dicates that exactly the data you need won't be in the backup. Far better is to remember to start a transaction in the first place, putting recovery a blood-pressure friendly ROLLBACK away. psql has two surprisingly little-used functions which help ensure you're inside a transaction when you need to be.

I've written about this before: psql has a prompt formatting option %x which displays an asterisk * whenever a transaction is in process. Set it with e.g. \set PROMPT1 '%/%R%x%# ' and train yourself to be very nervous about carrying out anything other than simple SELECTs when that little asterisk is not visible:

test=> \set PROMPT1 '%/%R%x%# '
test=> BEGIN;
test=*> DELETE FROM important_table;
DELETE 24566321
test=*> ROLLBACK;
test=> \echo Phew, that was close!
Phew, that was close!

(See the psql manual for further details)

Of course this still requires you to remember to issue the BEGIN instruction, because PostgreSQL's default setting is for AUTOCOMMIT to be on. Issuing \set AUTOCOMMIT off, especially in combination with the prompt setting above, provides a useful safety net:

test=> \set AUTOCOMMIT off
test=> DELETE FROM important_table;
DELETE 24566321
test=*> \echo Ooops!
test=*> ROLLBACK;

The risk here of course is closing psql before committing the transaction, implicitly rolling back any changes you wanted to make, but the asterisk in the prompt serves as a useful visual reminder.

Put \set PROMPT1 '%/%R%x%# ' and \set AUTOCOMMIT off in your .psqlrc file to make them permanent settings.

Posted at 4:51 AM