Try and see. Open psql and make some settings:
CREATE TABLE foo_bar(id integer primary key); CREATE TABLE spam_eggs( foo_bar_id integer not null references foo_bar(id) on delete cascade ); INSERT INTO foo_bar (id) VALUES (1),(2),(3),(4); INSERT INTO spam_eggs(foo_bar_id) VALUES (1),(2),(3),(4);
then open another psql connection. BEGIN transaction in both of them.
- In the first (old) session, execute
SELECT 1 FROM spam_eggs WHERE foo_bar_id = 4 FOR UPDATE; - In the second (new) session, run
DELETE FROM foo_bar WHERE id = 4;
You will see that the second statement blocks the first. This is because DELETE on foo_bar cascades to spam_eggs and tries to block the line using a foreign key reference so that it can delete it. This lock is locked by the lock held by SELECT ... FOR SHARE .
In general, try testing in all of these circumstances:
- tx
BEGIN ISOLATION LEVEL READ COMMITTED and first issues a ROLLBACK - tx
BEGIN ISOLATION LEVEL READ COMMITTED and first issues a COMMIT - tx
BEGIN ISOLATION LEVEL SERIALIZABLE and first issues a ROLLBACK - tx
BEGIN ISOLATION LEVEL SERIALIZABLE and first issues a COMMIT
to make sure you know what to expect. It is also good for your training if you reason what you expect before testing it.
In this case, the isolation levels READ COMMITTED and SERIALIZABLE will behave the same. If you actually do UPDATE after SELECT ... FOR UPDATE and then COMMIT , then they will behave differently; the READ COMMITTED version will be DELETE successful, and the SERIALIZABLE version will fail:
regress=# BEGIN ISOLATION LEVEL SERIALIZABLE; regress=# DELETE FROM foo_bar WHERE id = 4; ERROR: could not serialize access due to concurrent update CONTEXT: SQL statement "DELETE FROM ONLY "public"."spam_eggs" WHERE $1 OPERATOR(pg_catalog.=) "foo_bar_id""
source share