I have a table foo_bar and another table spam_eggs with a fb foreign key pointing to foo_bar. spam_eggs rows are cascade deleted when their related spam_eggs.fb are deleted.
I’m working with PostgreSQL.
In a transaction I have used SELECT... FOR UPDATE to lock a spam_eggs row. In the duration of this transaction, another transaction has attempted to DELETE FROM... the related foo_bar of my locked row. Will this trigger an error, or will my locked row cause the query to block until the end of my original update transaction?
Try it and see. Open
psqland do some setup:then open another psql connection.
BEGINa transaction in both of them.SELECT 1 FROM spam_eggs WHERE foo_bar_id = 4 FOR UPDATE;DELETE FROM foo_bar WHERE id = 4;You will see that the second statement blocks on the first. That’s because the
DELETEonfoo_barcascades tospam_eggsand attempts to lock the row with the foreign key reference so it can delete it. That lock blocks on the lock held by theSELECT ... FOR SHARE.In general, try to test in all these circumstances:
BEGIN ISOLATION LEVEL READ COMMITTEDand first issues aROLLBACKBEGIN ISOLATION LEVEL READ COMMITTEDand first issues aCOMMITBEGIN ISOLATION LEVEL SERIALIZABLEand first issues aROLLBACKBEGIN ISOLATION LEVEL SERIALIZABLEand first issues aCOMMITto make sure you know what to expect. It’s also good for your learning if you reason through what you expect to happen before testing it.
In this case the
READ COMMITTEDandSERIALIZABLEisolation levels will behave the same. If you actually do anUPDATEafter yourSELECT ... FOR UPDATEand thenCOMMITthen they’ll behave differently, though; theREAD COMMITTEDversion willDELETEsuccessfully, while theSERIALIZABLEversion will fail with: