Suppose I have this foo table in a PostgreSQL 9.1 database:
CREATE TABLE foo
(
bar integer,
flg_deleted boolean
);
Along with this vwfoo view:
CREATE VIEW vwfoo AS
SELECT bar
FROM foo
WHERE flg_deleted = false;
Also assume I have an application running a couple of short-lived transactions per second, using vwfoo.
Now, I want to add a column baz to foo and I want baz to be in vwfoo too. But, of course, I don’t want my application to get any errors because of those changes.
If I execute the following steps (in a single transaction) to perform the desired change:
- Drop vwfoo.
- Add column baz to foo.
- Create vwfoo again (now including baz).
Do I get the desired behavior (no errors in the application)?
Will there be an exclusive lock being held on vwfoo during the whole transaction (that’s what I want)?
Is it possible that any transaction will try to use the view between steps 1 and 3 and then fail (instead of just blocking, waiting for a lock)?
Does the “identity” of vwfoo change when it’s recreated? In other words: is it possible that any transaction will try to use the view between steps 1 and 3, block, resume after step 3 and then fail because the view was recreated?
Thanks.
A quick test suggests that this will cause problems with your application. To recreate, create two connections (
AandB), then run:Instead, you should do this kind of atomic swapping by renaming the views:
This will work as expected (and you won’t need to run a (comparatively) expensive
DROP TABLEinside the transaction!)Edit: You can use the same strategy to solve your “real” problem, too:
The view referencing
bar_newwill be correctly updated, too: