0

I have created a procedure in Postgres that will create a table with the contents of another three tables (SELECT with JOINS). Then the resulting table will be altered adding two columns that didnt exist before and finally within the same procedure I have created 3 triggers that will be applied on those three tables so anytime a new write happens on any of those, the same entity will be recorded in the new table

I know the procedure itself is atomic and that is transactional from its own scope, but the procedure has no means of knowing anything about the three tables. Im afraid that in the time between the new table creation and the creation of the triggers, some writes to the existing tables could happen thus desynchronizing the new table, which wont register those writes. That cannot happen.

My table creation/trigger creation procedure looks like this:

CREATE OR REPLACE PROCEDURE myschema.table_creation()
LANGUAGE plpgsql
AS $procedure$
begin
create table newtable as
SELECT * FROM myschema.session a NATURAL JOIN (SELECT * FROM myschema.message b NATURAL left JOIN myschema.data) as d;
ALTER TABLE myschema.newtable ADD created_at timestamp;
ALTER TABLE myschema.newtable ADD source text;
CREATE TRIGGER mytrigger
after INSERT
ON myschema.session
FOR EACH ROW
EXECUTE PROCEDURE myschema.trigger_proc();
CREATE TRIGGER mytrigger
after INSERT
ON myschema.messages
FOR EACH ROW
EXECUTE PROCEDURE myschema.trigger_proc();
CREATE TRIGGER mytrigger
after INSERT
ON myschema.data
FOR EACH ROW
EXECUTE PROCEDURE myschema.trigger_proc();
end;
$procedure$
; 

How can I lock the writes in the existing tables to postpone them until the whole table_creation procedure has finished? Otherwise I would have a race condition and some entities would be lost in the new table. i don't think my procedure in its current state has any protection against writes

3
  • Is this a trick question? There's a LOCK command... Commented Jul 29, 2024 at 17:03
  • Yeah, but there are dozens of variants of it. And maybe locking a whole table (3 in fact) would be like killing flies with a cannon Commented Jul 30, 2024 at 9:13
  • This is a re-post of the same question on SO. stackoverflow.com/q/78808105/939860 Please don't cross-post, but declare where else you posted if you do. Commented Jul 31, 2024 at 0:15

1 Answer 1

0

You can start your procedure with

LOCK myschema.session, myschema.message, myschema.data IN SHARE MODE;

That will lock out all concurrent data modifications.

It is no problem to lock a table for a one-time activity like that, but you should avoid taking high-level explicit table locks regularly, because they disrupt autovacuum processing.

4
  • It looked to me like locking a whole table was extreme. Is there another kind of soft locks to do that? I assume the only kind of lock that could be used is a table lock Commented Jul 30, 2024 at 9:53
  • It is extreme. But blocking data modifications is sort of extreme to begin with. Commented Jul 30, 2024 at 10:00
  • Yes of course. But after all we don't need to block reads, just new inserts. There are no update operations either for now but it could happen that one of the tables will have update ops in the future Commented Jul 30, 2024 at 10:07
  • 1
    Right, that's what a SHARE lock does. You can read, but not write. Commented Jul 30, 2024 at 10:45

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.