Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitccd21e1

Browse files
committed
Fix assertion failure when updating stats_fetch_consistency in a transaction
An update of the GUC stats_fetch_consistency in a transaction would beable to trigger an assertion when doing cache->snapshot. In this case,when retrieving a pgstat entry after the switch, a new snapshot would berebuilt, confusing pgstat_build_snapshot() because a snapshot is alreadycached with an unexpected mode ("cache").In order to fix this problem, this commit adds a flag to force asnapshot clear each time this GUC is changed. Some tests are added tocheck, while on it.Some optimizations in avoiding the snapshot clear should be possibledepending on what is cached and the current GUC value, I guess, but thissolution is simple, and ensures that the state of the cache is updatedeach time a new pgstat entry is fetched, hence being consistent with thelevel wanted by the client that has set the GUC.Note that cache->none and snapshot->none would not cause issues, asfetching a pgstat entry would be retrieved from shared memory on thesecond attempt, however a snapshot would still be cached. Similarly,none->snapshot and none->cache would build a new snapshot on the secondfetch attempt. Finally, snapshot->cache would cache a new snapshot onthe second attempt.Reported-by: Alexander LakhinAuthor: Kyotaro HoriguchiDiscussion:https://postgr.es/m/17804-2a118cd046f2d0e5@postgresql.orgbackpatch-through: 15
1 parent8382864 commitccd21e1

File tree

6 files changed

+118
-4
lines changed

6 files changed

+118
-4
lines changed

‎doc/src/sgml/config.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8064,8 +8064,9 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
80648064
called. When set to <literal>snapshot</literal>, the first statistics
80658065
access caches all statistics accessible in the current database, until
80668066
the end of the transaction unless
8067-
<function>pg_stat_clear_snapshot()</function> is called. The default
8068-
is <literal>cache</literal>.
8067+
<function>pg_stat_clear_snapshot()</function> is called. Changing this
8068+
parameter in a transaction discards the statistics snapshot.
8069+
The default is <literal>cache</literal>.
80698070
</para>
80708071
<note>
80718072
<para>

‎src/backend/utils/activity/pgstat.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,13 @@ static dlist_head pgStatPending = DLIST_STATIC_INIT(pgStatPending);
226226
*/
227227
staticboolpgStatForceNextFlush= false;
228228

229+
/*
230+
* Force-clear existing snapshot before next use when stats_fetch_consistency
231+
* is changed.
232+
*/
233+
staticboolforce_stats_snapshot_clear= false;
234+
235+
229236
/*
230237
* For assertions that check pgstat is not used before initialization / after
231238
* shutdown.
@@ -746,7 +753,8 @@ pgstat_reset_of_kind(PgStat_Kind kind)
746753
* request will cause new snapshots to be read.
747754
*
748755
* This is also invoked during transaction commit or abort to discard
749-
* the no-longer-wanted snapshot.
756+
* the no-longer-wanted snapshot. Updates of stats_fetch_consistency can
757+
* cause this routine to be called.
750758
*/
751759
void
752760
pgstat_clear_snapshot(void)
@@ -773,6 +781,9 @@ pgstat_clear_snapshot(void)
773781
* forward the reset request.
774782
*/
775783
pgstat_clear_backend_activity_snapshot();
784+
785+
/* Reset this flag, as it may be possible that a cleanup was forced. */
786+
force_stats_snapshot_clear= false;
776787
}
777788

778789
void*
@@ -871,6 +882,9 @@ pgstat_fetch_entry(PgStat_Kind kind, Oid dboid, Oid objoid)
871882
TimestampTz
872883
pgstat_get_stat_snapshot_timestamp(bool*have_snapshot)
873884
{
885+
if (force_stats_snapshot_clear)
886+
pgstat_clear_snapshot();
887+
874888
if (pgStatLocal.snapshot.mode==PGSTAT_FETCH_CONSISTENCY_SNAPSHOT)
875889
{
876890
*have_snapshot= true;
@@ -915,6 +929,9 @@ pgstat_snapshot_fixed(PgStat_Kind kind)
915929
staticvoid
916930
pgstat_prep_snapshot(void)
917931
{
932+
if (force_stats_snapshot_clear)
933+
pgstat_clear_snapshot();
934+
918935
if (pgstat_fetch_consistency==PGSTAT_FETCH_CONSISTENCY_NONE||
919936
pgStatLocal.snapshot.stats!=NULL)
920937
return;
@@ -1644,3 +1661,18 @@ pgstat_reset_after_failure(void)
16441661
/* and drop variable-numbered ones */
16451662
pgstat_drop_all_entries();
16461663
}
1664+
1665+
/*
1666+
* GUC assign_hook for stats_fetch_consistency.
1667+
*/
1668+
void
1669+
assign_stats_fetch_consistency(intnewval,void*extra)
1670+
{
1671+
/*
1672+
* Changing this value in a transaction may cause snapshot state
1673+
* inconsistencies, so force a clear of the current snapshot on the next
1674+
* snapshot build attempt.
1675+
*/
1676+
if (pgstat_fetch_consistency!=newval)
1677+
force_stats_snapshot_clear= true;
1678+
}

‎src/backend/utils/misc/guc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4948,7 +4948,7 @@ static struct config_enum ConfigureNamesEnum[] =
49484948
},
49494949
&pgstat_fetch_consistency,
49504950
PGSTAT_FETCH_CONSISTENCY_CACHE,stats_fetch_consistency,
4951-
NULL,NULL,NULL
4951+
NULL,assign_stats_fetch_consistency,NULL
49524952
},
49534953

49544954
{

‎src/include/pgstat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,8 @@ extern TimestampTz pgstat_get_stat_snapshot_timestamp(bool *have_snapshot);
432432
externPgStat_Kindpgstat_get_kind_from_str(char*kind_str);
433433
externboolpgstat_have_entry(PgStat_Kindkind,Oiddboid,Oidobjoid);
434434

435+
/* GUC hook for stats_fetch_consistency */
436+
externvoidassign_stats_fetch_consistency(intnewval,void*extra);
435437

436438
/*
437439
* Functions in pgstat_archiver.c

‎src/test/regress/expected/stats.out

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,65 @@ SELECT pg_stat_get_snapshot_timestamp();
766766

767767
COMMIT;
768768
----
769+
-- Changing stats_fetch_consistency in a transaction.
770+
----
771+
BEGIN;
772+
-- Stats filled under the cache mode
773+
SET LOCAL stats_fetch_consistency = cache;
774+
SELECT pg_stat_get_function_calls(0);
775+
pg_stat_get_function_calls
776+
----------------------------
777+
778+
(1 row)
779+
780+
SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok;
781+
snapshot_ok
782+
-------------
783+
f
784+
(1 row)
785+
786+
-- Success in accessing pre-existing snapshot data.
787+
SET LOCAL stats_fetch_consistency = snapshot;
788+
SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok;
789+
snapshot_ok
790+
-------------
791+
f
792+
(1 row)
793+
794+
SELECT pg_stat_get_function_calls(0);
795+
pg_stat_get_function_calls
796+
----------------------------
797+
798+
(1 row)
799+
800+
SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok;
801+
snapshot_ok
802+
-------------
803+
t
804+
(1 row)
805+
806+
-- Snapshot cleared.
807+
SET LOCAL stats_fetch_consistency = none;
808+
SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok;
809+
snapshot_ok
810+
-------------
811+
f
812+
(1 row)
813+
814+
SELECT pg_stat_get_function_calls(0);
815+
pg_stat_get_function_calls
816+
----------------------------
817+
818+
(1 row)
819+
820+
SELECT pg_stat_get_snapshot_timestamp() IS NOT NULL AS snapshot_ok;
821+
snapshot_ok
822+
-------------
823+
f
824+
(1 row)
825+
826+
ROLLBACK;
827+
----
769828
-- pg_stat_have_stats behavior
770829
----
771830
-- fixed-numbered stats exist

‎src/test/regress/sql/stats.sql

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,26 @@ SELECT pg_stat_clear_snapshot();
383383
SELECT pg_stat_get_snapshot_timestamp();
384384
COMMIT;
385385

386+
----
387+
-- Changing stats_fetch_consistency in a transaction.
388+
----
389+
BEGIN;
390+
-- Stats filled under the cache mode
391+
SET LOCAL stats_fetch_consistency= cache;
392+
SELECT pg_stat_get_function_calls(0);
393+
SELECT pg_stat_get_snapshot_timestamp()IS NOT NULLAS snapshot_ok;
394+
-- Success in accessing pre-existing snapshot data.
395+
SET LOCAL stats_fetch_consistency= snapshot;
396+
SELECT pg_stat_get_snapshot_timestamp()IS NOT NULLAS snapshot_ok;
397+
SELECT pg_stat_get_function_calls(0);
398+
SELECT pg_stat_get_snapshot_timestamp()IS NOT NULLAS snapshot_ok;
399+
-- Snapshot cleared.
400+
SET LOCAL stats_fetch_consistency= none;
401+
SELECT pg_stat_get_snapshot_timestamp()IS NOT NULLAS snapshot_ok;
402+
SELECT pg_stat_get_function_calls(0);
403+
SELECT pg_stat_get_snapshot_timestamp()IS NOT NULLAS snapshot_ok;
404+
ROLLBACK;
405+
386406
----
387407
-- pg_stat_have_stats behavior
388408
----

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp