Обсуждение: pg_get_indexdef() modification to use TxnSnapshot

Поиск
Список
Период
Сортировка

pg_get_indexdef() modification to use TxnSnapshot

От
shveta malik
Дата:
I have attempted to convert pg_get_indexdef() to use
systable_beginscan() based on transaction-snapshot rather than using
SearchSysCache(). The latter does not have any old info and thus
provides only the latest info as per the committed txns, which could
result in errors in some scenarios. One such case is mentioned atop
pg_dump.c. The patch is an attempt to fix the same pg_dump's issue.
Any feedback is welcome.

There is a long list of pg_get_* functions which use SearchSysCache()
and thus may expose similar issues. I can give it a try to review the
possibility of converting all of them. Thoughts?

thanks
Shveta

Вложения

Re: pg_get_indexdef() modification to use TxnSnapshot

От
vignesh C
Дата:
On Fri, 26 May 2023 at 15:25, shveta malik <shveta.malik@gmail.com> wrote:
>
> I have attempted to convert pg_get_indexdef() to use
> systable_beginscan() based on transaction-snapshot rather than using
> SearchSysCache(). The latter does not have any old info and thus
> provides only the latest info as per the committed txns, which could
> result in errors in some scenarios. One such case is mentioned atop
> pg_dump.c. The patch is an attempt to fix the same pg_dump's issue.
> Any feedback is welcome.
>
> There is a long list of pg_get_* functions which use SearchSysCache()
> and thus may expose similar issues. I can give it a try to review the
> possibility of converting all of them. Thoughts?

I could reproduce this issue in HEAD with pg_dump dumping a database
having a table and an index like:
create table t1(c1 int);
create index idx1 on t1(c1);

Steps to reproduce:
a) ./pg_dump -d postgres -f dump.txt -- Debug this statement and hold
a breakpoint at getTables function just before it takes lock on the
table t1 b) when the breakpoint is hit, drop the index idx1 c)
Continue the pg_dump execution after dropping the index d) pg_dump
calls pg_get_indexdef to get the index definition e) since
pg_get_indexdef->pg_get_indexdef uses SearchSysCache1 which uses the
latest transaction, it will not get the index information as it sees
the latest catalog snapshot(it will not get the index information). e)
pg_dump will get an empty index statement in this case like:
---------------------------------------------------------------------------------------------
--
-- Name: idx; Type: INDEX; Schema: public; Owner: vignesh
--

;
---------------------------------------------------------------------------------------------

This issue is solved using shveta's patch as it registers the
transaction snapshot and calls systable_beginscan which will not see
the transactions that were started after pg_dump's transaction(the
drop index will not be seen) and gets the index definition as expected
like:
---------------------------------------------------------------------------------------------
--
-- Name: idx; Type: INDEX; Schema: public; Owner: vignesh
--

CREATE INDEX idx ON public.t1 USING btree (c1);
---------------------------------------------------------------------------------------------

Regards,
Vignesh



Re: pg_get_indexdef() modification to use TxnSnapshot

От
Masahiko Sawada
Дата:
On Fri, May 26, 2023 at 6:55 PM shveta malik <shveta.malik@gmail.com> wrote:
>
> I have attempted to convert pg_get_indexdef() to use
> systable_beginscan() based on transaction-snapshot rather than using
> SearchSysCache(). The latter does not have any old info and thus
> provides only the latest info as per the committed txns, which could
> result in errors in some scenarios. One such case is mentioned atop
> pg_dump.c. The patch is an attempt to fix the same pg_dump's issue.
> Any feedback is welcome.

Even only in pg_get_indexdef_worker(), there are still many places
where we use syscache lookup: generate_relation_name(),
get_relation_name(), get_attname(), get_atttypetypmodcoll(),
get_opclass_name() etc.

>
> There is a long list of pg_get_* functions which use SearchSysCache()
> and thus may expose similar issues. I can give it a try to review the
> possibility of converting all of them. Thoughts?
>

it would be going to be a large refactoring and potentially make the
future implementations such as pg_get_tabledef() etc hard. Have you
considered changes to the SearchSysCache() family so that they
internally use a transaction snapshot that is registered in advance.
Since we are already doing similar things for catalog lookup in
logical decoding, it might be feasible. That way, the changes to
pg_get_XXXdef() functions would be much easier.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: pg_get_indexdef() modification to use TxnSnapshot

От
vignesh C
Дата:
On Tue, 13 Jun 2023 at 11:49, Masahiko Sawada <sawada.mshk@gmail.com> wrote:
>
> On Fri, May 26, 2023 at 6:55 PM shveta malik <shveta.malik@gmail.com> wrote:
> >
> > I have attempted to convert pg_get_indexdef() to use
> > systable_beginscan() based on transaction-snapshot rather than using
> > SearchSysCache(). The latter does not have any old info and thus
> > provides only the latest info as per the committed txns, which could
> > result in errors in some scenarios. One such case is mentioned atop
> > pg_dump.c. The patch is an attempt to fix the same pg_dump's issue.
> > Any feedback is welcome.
>
> Even only in pg_get_indexdef_worker(), there are still many places
> where we use syscache lookup: generate_relation_name(),
> get_relation_name(), get_attname(), get_atttypetypmodcoll(),
> get_opclass_name() etc.
>
> >
> > There is a long list of pg_get_* functions which use SearchSysCache()
> > and thus may expose similar issues. I can give it a try to review the
> > possibility of converting all of them. Thoughts?
> >
>
> it would be going to be a large refactoring and potentially make the
> future implementations such as pg_get_tabledef() etc hard. Have you
> considered changes to the SearchSysCache() family so that they
> internally use a transaction snapshot that is registered in advance.
> Since we are already doing similar things for catalog lookup in
> logical decoding, it might be feasible. That way, the changes to
> pg_get_XXXdef() functions would be much easier.

I feel registering an active snapshot before accessing the system
catalog as suggested by Sawada-san will be a better fix to solve the
problem. If this approach is fine, we will have to similarly fix the
other pg_get_*** functions like pg_get_constraintdef,
pg_get_function_arguments, pg_get_function_result,
pg_get_function_identity_arguments, pg_get_function_sqlbody,
pg_get_expr, pg_get_partkeydef, pg_get_statisticsobjdef and
pg_get_triggerdef.
The Attached patch has the changes for the same.

Regards,
Vignesh

Вложения

Re: pg_get_indexdef() modification to use TxnSnapshot

От
kuroda.keisuke@nttcom.co.jp
Дата:
Hi hackers,

With '0001-pg_get_indexdef-modification-to-access-catalog-based.patch'
patch,
I confirmed that definition information
can be collected even if the index is droped during pg_dump.
The regression test (make check-world) has passed.

I also tested the view definition for a similar problem.
As per the attached patch and test case,
By using SetupHistoricSnapshot for pg_get_viewdef() as well,
Similarly, definition information can be collected
for VIEW definitions even if the view droped during pg_dump.
The regression test (make check-world) has passed,
and pg_dump's SERIALIZABLE results are improved.
However, in a SERIALIZABLE transaction,
If you actually try to access it, it will cause ERROR,
so it seems to cause confusion.
I think the scope of this improvement should be limited
to the functions listed as pg_get_*** functions at the moment.

---

# test2 pg_get_indexdef,pg_get_viewdef

## create table,index,view
drop table test1;
create table test1(id int);
create index idx1_test1 on test1(id);
create view view1_test1 as select * from test1;

## begin Transaction-A
begin transaction isolation level serializable;
select pg_current_xact_id();

## begin Transaction-B
begin transaction isolation level serializable;
select pg_current_xact_id();

## drop index,view in Transaction-A
drop index idx1_test1;
drop view view1_test1;
commit;

## SELECT pg_get_indexdef,pg_get_viewdef in Transaction-B
SELECT pg_get_indexdef(oid) FROM pg_class WHERE relname = 'idx1_test1';
SELECT pg_get_viewdef(oid) FROM pg_class WHERE relname = 'view1_test1';

## correct info from index and view
postgres=*# SELECT pg_get_indexdef(oid) FROM pg_class WHERE relname =
'idx1_test1';
                      pg_get_indexdef
----------------------------------------------------------
  CREATE INDEX idx1_test1 ON public.test1 USING btree (id)
(1 row)

postgres=*# SELECT pg_get_viewdef(oid) FROM pg_class WHERE relname =
'view1_test1';
  pg_get_viewdef
----------------
   SELECT id    +
     FROM test1;
(1 row)

## However, SELECT * FROM view1_test1 cause ERROR because view does not
exist
postgres=*# SELECT * FROM view1_test1;
ERROR:  relation "view1_test1" does not exist
LINE 1: SELECT * FROM view1_test1;

Best Regards,
Keisuke Kuroda
NTT COMWARE

On 2023-06-14 15:31, vignesh C wrote:
> On Tue, 13 Jun 2023 at 11:49, Masahiko Sawada <sawada.mshk@gmail.com>
> wrote:
>>
>> On Fri, May 26, 2023 at 6:55 PM shveta malik <shveta.malik@gmail.com>
>> wrote:
>> >
>> > I have attempted to convert pg_get_indexdef() to use
>> > systable_beginscan() based on transaction-snapshot rather than using
>> > SearchSysCache(). The latter does not have any old info and thus
>> > provides only the latest info as per the committed txns, which could
>> > result in errors in some scenarios. One such case is mentioned atop
>> > pg_dump.c. The patch is an attempt to fix the same pg_dump's issue.
>> > Any feedback is welcome.
>>
>> Even only in pg_get_indexdef_worker(), there are still many places
>> where we use syscache lookup: generate_relation_name(),
>> get_relation_name(), get_attname(), get_atttypetypmodcoll(),
>> get_opclass_name() etc.
>>
>> >
>> > There is a long list of pg_get_* functions which use SearchSysCache()
>> > and thus may expose similar issues. I can give it a try to review the
>> > possibility of converting all of them. Thoughts?
>> >
>>
>> it would be going to be a large refactoring and potentially make the
>> future implementations such as pg_get_tabledef() etc hard. Have you
>> considered changes to the SearchSysCache() family so that they
>> internally use a transaction snapshot that is registered in advance.
>> Since we are already doing similar things for catalog lookup in
>> logical decoding, it might be feasible. That way, the changes to
>> pg_get_XXXdef() functions would be much easier.
>
> I feel registering an active snapshot before accessing the system
> catalog as suggested by Sawada-san will be a better fix to solve the
> problem. If this approach is fine, we will have to similarly fix the
> other pg_get_*** functions like pg_get_constraintdef,
> pg_get_function_arguments, pg_get_function_result,
> pg_get_function_identity_arguments, pg_get_function_sqlbody,
> pg_get_expr, pg_get_partkeydef, pg_get_statisticsobjdef and
> pg_get_triggerdef.
> The Attached patch has the changes for the same.
>
> Regards,
> Vignesh
Вложения

Re: pg_get_indexdef() modification to use TxnSnapshot

От
Tom Lane
Дата:
kuroda.keisuke@nttcom.co.jp writes:
> On 2023-06-14 15:31, vignesh C wrote:
>> I have attempted to convert pg_get_indexdef() to use
>> systable_beginscan() based on transaction-snapshot rather than using
>> SearchSysCache().

Has anybody thought about the fact that ALTER TABLE ALTER TYPE
(specifically RememberIndexForRebuilding) absolutely requires seeing
the latest version of the index's definition?

>>> it would be going to be a large refactoring and potentially make the
>>> future implementations such as pg_get_tabledef() etc hard. Have you
>>> considered changes to the SearchSysCache() family so that they
>>> internally use a transaction snapshot that is registered in advance.

A very significant fraction of other SearchSysCache callers likewise
cannot afford to see stale data.  We might be able to fix things so
that the SQL-accessible ruleutils functionality works differently, but
we can't just up and change the behavior of cache lookups everywhere.

            regards, tom lane



Re: pg_get_indexdef() modification to use TxnSnapshot

От
Robert Haas
Дата:
On Thu, Oct 5, 2023 at 11:15 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
> kuroda.keisuke@nttcom.co.jp writes:
> > On 2023-06-14 15:31, vignesh C wrote:
> >> I have attempted to convert pg_get_indexdef() to use
> >> systable_beginscan() based on transaction-snapshot rather than using
> >> SearchSysCache().
>
> Has anybody thought about the fact that ALTER TABLE ALTER TYPE
> (specifically RememberIndexForRebuilding) absolutely requires seeing
> the latest version of the index's definition?
>
> >>> it would be going to be a large refactoring and potentially make the
> >>> future implementations such as pg_get_tabledef() etc hard. Have you
> >>> considered changes to the SearchSysCache() family so that they
> >>> internally use a transaction snapshot that is registered in advance.
>
> A very significant fraction of other SearchSysCache callers likewise
> cannot afford to see stale data.  We might be able to fix things so
> that the SQL-accessible ruleutils functionality works differently, but
> we can't just up and change the behavior of cache lookups everywhere.

This patch was registered in the CommitFest as a bug fix, but I think
it's a much more significant change than that label applies, and it
seems like we have no consensus on what the right design is.

Since there's been no response to these (entirely valid) comments from
Tom in the past 3 months, I've marked this CF entry RwF for now.

--
Robert Haas
EDB: http://www.enterprisedb.com