On Thu, Mar 5, 2026 at 12:11 PM Fujii Masao <[email protected]> wrote:
> I haven't yet realized the benefit from this change since I haven't
> encountered issues caused by the current behavior (i.e., a remote transaction
> starting in read-write mode while the corresponding local transaction on
> the standby is read-only).
>
> On the other hand, this change would force any remote transaction initiated by
> a standby transaction to start in read-only mode, completely preventing it
> from
> modifying data. Because transactions on a standby always start as read-only,
> the remote transaction would also always be read-only under this proposal,
> with no way to make it read-write.
>
> I'm concerned that this could break certain use cases without providing
> a clear benefit.
Thanks for the comments!
The benefit is to make read-only transactions using postgres_fdw
ensure read-only access. We discussed this in a Postgres developer
meetup held at Yokohama in Japan last Friday. Let me explain again.
Here is an example I used in that meetup to show the current behavior
of such transactions:
create server loopback
foreign data wrapper postgres_fdw
options (dbname 'postgres');
create user mapping for current_user
server loopback;
create table loct (f1 int, f2 text);
create foreign table ft (f1 int, f2 text)
server loopback
options (table_name 'loct');
insert into ft values (1, 'foo');
insert into ft values (2, 'bar');
They disallow INSERT/UPDATE/DELETE, which is good:
start transaction read only;
insert into ft values (3, 'baz');
ERROR: cannot execute INSERT in a read-only transaction
start transaction read only;
update ft set f2 = 'xyzzy';
ERROR: cannot execute UPDATE in a read-only transaction
start transaction read only;
delete from ft;
ERROR: cannot execute DELETE in a read-only transaction
But if referencing foreign tables mapped to a remote view executing
functions that modify data at the remote side, they can modify the
data, which would be surprising:
create function locf() returns setof loct language sql as
'update public.loct set f2 = f2 || f2 returning *';
create view locv as select t.* from locf() t;
create foreign table fv (f1 int, f2 text)
server loopback
options (table_name 'locv');
start transaction read only;
select * from fv;
f1 | f2
----+--------
1 | foofoo
2 | barbar
(2 rows)
The root cause of this is that postgres_fdw opens a remote transaction
in read-write mode even if the local transaction is read-only, so the
patch I proposed addresses this by inheriting the read-only property
from the local transaction.
I didn't think of the use cases where postgres_fdw is used on a
standby server, so I overlooked the breakage you mentioned above, but
I got a lot of positive feedback from many participants regarding
ensuring read-only access by that change. So I strongly believe the
patch is the right way to go. I think it's unfortunate that it causes
the breakage, though. I might be missing something, but I think a
solution for such a use case is to use other DB integration tool like
dblink.
Anyway, I would like to know what other people think.
Best regards,
Etsuro Fujita