agora inbox for [email protected]help / color / mirror / Atom feed
[PATCH v25 4/5] Add ALTER INDEX ... ALTER COLLATION ... REFRESH VERSION. 4+ messages / 2 participants [nested] [flat]
* [PATCH v25 4/5] Add ALTER INDEX ... ALTER COLLATION ... REFRESH VERSION. @ 2019-12-11 12:54 Julien Rouhaud <[email protected]> 0 siblings, 0 replies; 4+ messages in thread From: Julien Rouhaud @ 2019-12-11 12:54 UTC (permalink / raw) This command allows privileged users to specify that the currently installed collation version, for a specific collation, is binary compatible with the one that was installed when the specified index was built. This provides a way to clear warnings about potentially corrupted indexes without having to use REINDEX. Author: Julien Rouhaud Reviewed-by: Laurenz Albe, Thomas Munro and Peter Eisentraut Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/ref/alter_index.sgml | 17 +++++++ src/backend/catalog/index.c | 2 +- src/backend/commands/tablecmds.c | 46 +++++++++++++++++++ src/backend/nodes/copyfuncs.c | 1 + src/backend/parser/gram.y | 8 ++++ src/bin/psql/tab-complete.c | 27 ++++++++++- src/include/catalog/index.h | 3 ++ src/include/nodes/parsenodes.h | 4 +- .../regress/expected/collate.icu.utf8.out | 20 ++++++++ src/test/regress/sql/collate.icu.utf8.sql | 11 +++++ 10 files changed, 136 insertions(+), 3 deletions(-) diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml index a5e3b06ee4..03355164b3 100644 --- a/doc/src/sgml/ref/alter_index.sgml +++ b/doc/src/sgml/ref/alter_index.sgml @@ -25,6 +25,7 @@ ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RENA ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET TABLESPACE <replaceable class="parameter">tablespace_name</replaceable> ALTER INDEX <replaceable class="parameter">name</replaceable> ATTACH PARTITION <replaceable class="parameter">index_name</replaceable> ALTER INDEX <replaceable class="parameter">name</replaceable> DEPENDS ON EXTENSION <replaceable class="parameter">extension_name</replaceable> +ALTER INDEX <replaceable class="parameter">name</replaceable> ALTER COLLATION <replaceable class="parameter">collation_name</replaceable> REFRESH VERSION ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> SET ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] ) ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> RESET ( <replaceable class="parameter">storage_parameter</replaceable> [, ... ] ) ALTER INDEX [ IF EXISTS ] <replaceable class="parameter">name</replaceable> ALTER [ COLUMN ] <replaceable class="parameter">column_number</replaceable> @@ -112,6 +113,22 @@ ALTER INDEX ALL IN TABLESPACE <replaceable class="parameter">name</replaceable> </listitem> </varlistentry> + <varlistentry> + <term><literal>ALTER COLLATION <replaceable class="parameter">collation_name</replaceable> REFRESH VERSION</literal></term> + <listitem> + <para> + This command declares that the index is compatible with the currently + installed version of a collation that determines its order. It is used + to silence warnings caused by collation version incompatibilities and + should be issued only if the collation ordering is known not to have + changed since the index was last built. Be aware that incorrect use of + this command can hide index corruption. If you don't know whether a + collation's definition has changed, using <xref linkend="sql-reindex"/> + is a safe alternative. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><literal>SET ( <replaceable class="parameter">storage_parameter</replaceable> [= <replaceable class="parameter">value</replaceable>] [, ... ] )</literal></term> <listitem> diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index e85aeb5502..ef2b896b6f 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -3156,7 +3156,7 @@ index_build(Relation heapRelation, SetUserIdAndSecContext(save_userid, save_sec_context); } -static char * +char * index_force_collation_version(const ObjectAddress *otherObject, const char *version, void *userdata) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f79044f39f..cdf3cbf5b1 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -93,6 +93,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/partcache.h" +#include "utils/pg_locale.h" #include "utils/relcache.h" #include "utils/ruleutils.h" #include "utils/snapmgr.h" @@ -556,6 +557,7 @@ static void refuseDupeIndexAttach(Relation parentIdx, Relation partIdx, Relation partitionTbl); static List *GetParentedForeignKeyRefs(Relation partition); static void ATDetachCheckNoForeignKeyRefs(Relation partition); +static void ATExecAlterCollationRefreshVersion(Relation rel, List *coll); /* ---------------------------------------------------------------- @@ -3926,6 +3928,10 @@ AlterTableGetLockLevel(List *cmds) cmd_lockmode = AccessShareLock; break; + case AT_AlterCollationRefreshVersion: + cmd_lockmode = AccessExclusiveLock; + break; + default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); @@ -4093,6 +4099,12 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, /* This command never recurses */ pass = AT_PASS_MISC; break; + case AT_AlterCollationRefreshVersion: /* ALTER COLLATION ... REFRESH + * VERSION */ + ATSimplePermissions(rel, ATT_INDEX); + /* This command never recurses */ + pass = AT_PASS_MISC; + break; case AT_SetStorage: /* ALTER COLUMN SET STORAGE */ ATSimplePermissions(rel, ATT_TABLE | ATT_MATVIEW | ATT_FOREIGN_TABLE); ATSimpleRecursion(wqueue, rel, cmd, recurse, lockmode, context); @@ -4659,6 +4671,11 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel, Assert(rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE); ATExecDetachPartition(rel, ((PartitionCmd *) cmd->def)->name); break; + case AT_AlterCollationRefreshVersion: + /* ATPrepCmd ensured it must be an index */ + Assert(rel->rd_rel->relkind == RELKIND_INDEX); + ATExecAlterCollationRefreshVersion(rel, cmd->object); + break; default: /* oops */ elog(ERROR, "unrecognized alter table type: %d", (int) cmd->subtype); @@ -17477,3 +17494,32 @@ ATDetachCheckNoForeignKeyRefs(Relation partition) table_close(rel, NoLock); } } + +/* Execute an ALTER INDEX ... ALTER COLLATION ... REFRESH VERSION + * + * This override an existing dependency on a specific collation for a specific + * index to depend on the current collation version. + */ +static void +ATExecAlterCollationRefreshVersion(Relation rel, List *coll) +{ + ObjectAddress object; + NewCollationVersionDependency forced_dependency; + + Assert(coll != NIL); + forced_dependency.oid = get_collation_oid(coll, false); + + /* Retrieve the current version for the CURRENT VERSION case. */ + Assert(OidIsValid(forced_dependency.oid)); + forced_dependency.version = + get_collation_version_for_oid(forced_dependency.oid); + + object.classId = RelationRelationId; + object.objectId = rel->rd_id; + object.objectSubId = 0; + visitDependentObjects(&object, &index_force_collation_version, + &forced_dependency); + + /* Invalidate the index relcache */ + CacheInvalidateRelcache(rel); +} diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 5cbbe3ba2e..ebf9118f4f 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3217,6 +3217,7 @@ _copyAlterTableCmd(const AlterTableCmd *from) COPY_SCALAR_FIELD(subtype); COPY_STRING_FIELD(name); + COPY_NODE_FIELD(object); COPY_SCALAR_FIELD(num); COPY_NODE_FIELD(newowner); COPY_NODE_FIELD(def); diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index c43b16037e..68934bfeb1 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -2594,6 +2594,14 @@ alter_table_cmd: n->subtype = AT_NoForceRowSecurity; $$ = (Node *)n; } + /* ALTER INDEX <name> ALTER COLLATION ... REFRESH VERSION */ + | ALTER COLLATION any_name REFRESH VERSION_P + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_AlterCollationRefreshVersion; + n->object = $3; + $$ = (Node *)n; + } | alter_generic_options { AlterTableCmd *n = makeNode(AlterTableCmd); diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index eb018854a5..ec0ef1feae 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -45,6 +45,7 @@ #include "catalog/pg_am_d.h" #include "catalog/pg_class_d.h" +#include "catalog/pg_collation_d.h" #include "common.h" #include "libpq-fe.h" #include "pqexpbuffer.h" @@ -814,6 +815,20 @@ static const SchemaQuery Query_for_list_of_statistics = { " (SELECT tgrelid FROM pg_catalog.pg_trigger "\ " WHERE pg_catalog.quote_ident(tgname)='%s')" +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_list_of_colls_for_one_index \ +" SELECT DISTINCT pg_catalog.quote_ident(coll.collname) " \ +" FROM pg_catalog.pg_depend d, pg_catalog.pg_collation coll, " \ +" pg_catalog.pg_class c" \ +" WHERE (%d = pg_catalog.length('%s'))" \ +" AND d.refclassid = " CppAsString2(CollationRelationId) \ +" AND d.refobjid = coll.oid " \ +" AND d.classid = " CppAsString2(RelationRelationId) \ +" AND d.objid = c.oid " \ +" AND c.relkind = " CppAsString2(RELKIND_INDEX) \ +" AND pg_catalog.pg_table_is_visible(c.oid) " \ +" AND c.relname = '%s'" + #define Query_for_list_of_ts_configurations \ "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\ " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'" @@ -1709,7 +1724,8 @@ psql_completion(const char *text, int start, int end) /* ALTER INDEX <name> */ else if (Matches("ALTER", "INDEX", MatchAny)) COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET", - "RESET", "ATTACH PARTITION", "DEPENDS", "NO DEPENDS"); + "RESET", "ATTACH PARTITION", "DEPENDS", "NO DEPENDS", + "ALTER COLLATION"); else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH")) COMPLETE_WITH("PARTITION"); else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION")) @@ -1759,6 +1775,15 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH("ON EXTENSION"); else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS")) COMPLETE_WITH("ON EXTENSION"); + /* ALTER INDEX <name> ALTER COLLATION */ + else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLLATION")) + { + completion_info_charp = prev4_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_colls_for_one_index); + } + /* ALTER INDEX <name> ALTER COLLATION <name> */ + else if (Matches("ALTER", "INDEX", MatchAny, "ALTER", "COLLATION", MatchAny)) + COMPLETE_WITH("REFRESH VERSION"); /* ALTER LANGUAGE <name> */ else if (Matches("ALTER", "LANGUAGE", MatchAny)) diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h index 9b4de26514..46d5df1613 100644 --- a/src/include/catalog/index.h +++ b/src/include/catalog/index.h @@ -123,6 +123,9 @@ extern void FormIndexDatum(IndexInfo *indexInfo, extern void index_check_collation_versions(Oid relid); +extern char *index_force_collation_version(const ObjectAddress *otherObject, + const char *version, + void *userdata); extern void index_force_collation_versions(Oid indexid, Oid coll, char *version); diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 7a23fb7529..423f33b72c 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1847,7 +1847,8 @@ typedef enum AlterTableType AT_DetachPartition, /* DETACH PARTITION */ AT_AddIdentity, /* ADD IDENTITY */ AT_SetIdentity, /* SET identity column options */ - AT_DropIdentity /* DROP IDENTITY */ + AT_DropIdentity, /* DROP IDENTITY */ + AT_AlterCollationRefreshVersion /* ALTER COLLATION ... REFRESH VERSION */ } AlterTableType; typedef struct ReplicaIdentityStmt @@ -1863,6 +1864,7 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ AlterTableType subtype; /* Type of table alteration to apply */ char *name; /* column, constraint, or trigger to act on, * or tablespace */ + List *object; /* collation to act on if it's a collation */ int16 num; /* attribute number for columns referenced by * number */ RoleSpec *newowner; diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out index db386c1b09..adc1dddda7 100644 --- a/src/test/regress/expected/collate.icu.utf8.out +++ b/src/test/regress/expected/collate.icu.utf8.out @@ -2054,6 +2054,26 @@ SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; ------- (0 rows) +-- Test ALTER INDEX name ALTER COLLATION name REFRESH VERSION +UPDATE pg_depend SET refobjversion = 'not a version' +WHERE refclassid = 'pg_collation'::regclass +AND objid::regclass::text = 'icuidx17_part' +AND refobjversion IS NOT NULL; +SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; + objid +--------------- + icuidx17_part +(1 row) + +ALTER INDEX icuidx17_part ALTER COLLATION "en-x-icu" REFRESH VERSION; +SELECT objid::regclass, refobjversion = 'not a version' AS ver FROM pg_depend +WHERE refclassid = 'pg_collation'::regclass +AND objid::regclass::text = 'icuidx17_part'; + objid | ver +---------------+----- + icuidx17_part | f +(1 row) + -- cleanup RESET search_path; SET client_min_messages TO warning; diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql index e93530af55..b3a75b29e6 100644 --- a/src/test/regress/sql/collate.icu.utf8.sql +++ b/src/test/regress/sql/collate.icu.utf8.sql @@ -823,6 +823,17 @@ VACUUM FULL collate_part_1; SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; +-- Test ALTER INDEX name ALTER COLLATION name REFRESH VERSION +UPDATE pg_depend SET refobjversion = 'not a version' +WHERE refclassid = 'pg_collation'::regclass +AND objid::regclass::text = 'icuidx17_part' +AND refobjversion IS NOT NULL; +SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; +ALTER INDEX icuidx17_part ALTER COLLATION "en-x-icu" REFRESH VERSION; +SELECT objid::regclass, refobjversion = 'not a version' AS ver FROM pg_depend +WHERE refclassid = 'pg_collation'::regclass +AND objid::regclass::text = 'icuidx17_part'; + -- cleanup RESET search_path; SET client_min_messages TO warning; -- 2.20.1 --lrZ03NoBR/3+SXJZ Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="v25-0005-doc-Add-Collation-Versions-section.patch" ^ permalink raw reply [nested|flat] 4+ messages in thread
* [PATCH v68 20/31] pgstat: test: stats handling of restarts, including crashes. @ 2022-03-20 20:33 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 4+ messages in thread From: Melanie Plageman @ 2022-03-20 20:33 UTC (permalink / raw) Stats should not be restored if the db crashed. Also, ensure invalid stats files are handled gracefully. Author: Melanie Plageman <[email protected]> Author: Andres Freund <[email protected]> Discussion: https://postgr.es/m/[email protected] --- src/test/recovery/t/029_stats_restart.pl | 305 +++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 src/test/recovery/t/029_stats_restart.pl diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl new file mode 100644 index 00000000000..55534b3a68d --- /dev/null +++ b/src/test/recovery/t/029_stats_restart.pl @@ -0,0 +1,305 @@ +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +# Tests statistics handling around restarts, including handling of crashes and +# invalid stats files, as well as restorting stats after "normal" restarts. + +use strict; +use warnings; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; +use File::Copy; + +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init(allows_streaming => 1); +$node->start; +$node->append_conf('postgresql.conf', "track_functions = 'all'"); +$node->reload; + +my $connect_db = 'postgres'; +my $db_under_test = 'test'; + +$node->safe_psql($connect_db, "CREATE DATABASE $db_under_test"); + +# Create table in test db +$node->safe_psql($db_under_test, + "CREATE TABLE tab_stats_crash_discard_test1 AS SELECT generate_series(1,100) AS a" +); + +# Create function in test db +$node->safe_psql($db_under_test, + "CREATE FUNCTION func_stats_crash_discard1() RETURNS VOID AS 'select 2;' LANGUAGE SQL IMMUTABLE" +); + +# collect object oids +my $dboid = $node->safe_psql($db_under_test, + "SELECT oid FROM pg_database WHERE datname = '$db_under_test'"); +my $funcoid = $node->safe_psql($db_under_test, + "SELECT 'func_stats_crash_discard1()'::regprocedure::oid"); +my $tableoid = $node->safe_psql($db_under_test, + "SELECT 'tab_stats_crash_discard_test1'::regclass::oid"); + +# generate stats and flush them +trigger_funcrel_stat(); + +# verify stats objects exist +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Regular shutdown +$node->stop(); + +# Backup stats files +my $statsfile = $PostgreSQL::Test::Utils::tmp_check . '/' . "discard_stats1"; +ok(!-f "$statsfile", "Backup statsfile cannot already exist"); + +my $datadir = $node->data_dir(); +my $og_stats = $datadir . '/' . "pg_stat" . '/' . "pgstat.stat"; +ok(-f "$og_stats", "Origin stats file must exist"); +copy($og_stats, $statsfile) or die "Copy failed: $!"; + +# Start the server +$node->start; + +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Fast shutdown +$node->stop('immediate'); + +ok(!-f "$og_stats", "No stats file should exist after immediate shutdown."); + +# Copy the old stats back to test we discard stats after crash restart +copy($statsfile, $og_stats) or die "Copy failed: $!"; + +# Start the server +$node->start; + +# Stats should have been discarded +is(exists_stat('database', $dboid, 0), + 'f', "Check that db stat does not exist."); +is(exists_stat('function', $dboid, $funcoid), + 'f', "Check that function stat does not exist."); +is(exists_stat('relation', $dboid, $tableoid), + 'f', "Check that relation stat does not exist."); + +# Get rid of backup statsfile +unlink $statsfile or die "cannot unlink $statsfile $!"; + + +# generate new stats and flush them +trigger_funcrel_stat(); + +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Regular shutdown +$node->stop(); + +sub overwrite_file +{ + my ($filename, $str) = @_; + open my $fh, ">", $filename + or die "could not write \"$filename\": $!"; + print $fh $str; + close $fh; + return; +} + +overwrite_file($og_stats, "ZZZZZZZZZZZZZ"); + +# Normal startup and no issues despite invalid stats file +$node->start; + +# No stats present due to invalid stats file +is(exists_stat('database', $dboid, 0), + 'f', "Check that db stat does not exist."); +is(exists_stat('function', $dboid, $funcoid), + 'f', "Check that function stat does not exist."); +is(exists_stat('relation', $dboid, $tableoid), + 'f', "Check that relation stat does not exist."); + + +## Checks related to stats persistency around restarts and resets + +# Ensure enough checkpoints to protect against races for test after reset, +# even on very slow machines. +$node->safe_psql($connect_db, "CHECKPOINT; CHECKPOINT;"); + + +## check checkpoint and wal stats are incremented due to restart + +my $ckpt_start = checkpoint_stats(); +my $wal_start = wal_stats(); +$node->restart; + +my $sect = "post restart"; +my $ckpt_restart = checkpoint_stats(); +my $wal_restart = wal_stats(); + +cmp_ok( + $ckpt_start->{count}, '<', + $ckpt_restart->{count}, + "$sect: increased checkpoint count"); +cmp_ok( + $wal_start->{records}, '<', + $wal_restart->{records}, + "$sect: increased wal record count"); +cmp_ok($wal_start->{bytes}, '<', $wal_restart->{bytes}, + "$sect: increased wal bytes"); +is( $ckpt_start->{reset}, + $ckpt_restart->{reset}, + "$sect: checkpoint stats_reset equal"); +is($wal_start->{reset}, $wal_restart->{reset}, + "$sect: wal stats_reset equal"); + + +## Check that checkpoint stats are reset, WAL stats aren't affected + +$node->safe_psql($connect_db, "SELECT pg_stat_reset_shared('bgwriter')"); + +$sect = "post ckpt reset"; +my $ckpt_reset = checkpoint_stats(); +my $wal_ckpt_reset = wal_stats(); + +cmp_ok($ckpt_restart->{count}, + '>', $ckpt_reset->{count}, "$sect: checkpoint count smaller"); +cmp_ok($ckpt_start->{reset}, 'lt', $ckpt_reset->{reset}, + "$sect: stats_reset newer"); + +cmp_ok( + $wal_restart->{records}, + '<=', + $wal_ckpt_reset->{records}, + "$sect: wal record count not affected by reset"); +is( $wal_start->{reset}, + $wal_ckpt_reset->{reset}, + "$sect: wal stats_reset equal"); + + +## check that checkpoint stats stay reset after restart + +$node->restart; + +$sect = "post ckpt reset & restart"; +my $ckpt_restart_reset = checkpoint_stats(); +my $wal_restart2 = wal_stats(); + +# made sure above there's enough checkpoints that this will be stable even on slow machines +cmp_ok( + $ckpt_restart_reset->{count}, + '<', + $ckpt_restart->{count}, + "$sect: checkpoint still reset"); +is($ckpt_restart_reset->{reset}, + $ckpt_reset->{reset}, "$sect: stats_reset same"); + +cmp_ok( + $wal_ckpt_reset->{records}, + '<', + $wal_restart2->{records}, + "$sect: increased wal record count"); +cmp_ok( + $wal_ckpt_reset->{bytes}, + '<', + $wal_restart2->{bytes}, + "$sect: increased wal bytes"); +is( $wal_start->{reset}, + $wal_restart2->{reset}, + "$sect: wal stats_reset equal"); + + +## check WAL stats stay reset + +$node->safe_psql($connect_db, "SELECT pg_stat_reset_shared('wal')"); + +$sect = "post wal reset"; +my $wal_reset = wal_stats(); + +cmp_ok( + $wal_reset->{records}, '<', + $wal_restart2->{records}, + "$sect: smaller record count"); +cmp_ok( + $wal_reset->{bytes}, '<', + $wal_restart2->{bytes}, + "$sect: smaller bytes"); +cmp_ok( + $wal_reset->{reset}, 'gt', + $wal_restart2->{reset}, + "$sect: newer stats_reset"); + +$node->restart; + +$sect = "post wal reset & restart"; +my $wal_reset_restart = wal_stats(); + +# enough WAL generated during prior tests and initdb to make this not racy +cmp_ok( + $wal_reset_restart->{records}, + '<', + $wal_restart2->{records}, + "$sect: smaller record count"); +cmp_ok( + $wal_reset->{bytes}, '<', + $wal_restart2->{bytes}, + "$sect: smaller bytes"); +cmp_ok( + $wal_reset->{reset}, 'gt', + $wal_restart2->{reset}, + "$sect: newer stats_reset"); + + +$node->stop; +done_testing(); + +sub trigger_funcrel_stat +{ + $node->safe_psql( + $db_under_test, q[ + SELECT * FROM tab_stats_crash_discard_test1; + SELECT func_stats_crash_discard1(); + SELECT pg_stat_force_next_flush();]); +} + +sub exists_stat +{ + my ($kind, $dboid, $objoid) = @_; + + return $node->safe_psql($connect_db, + "SELECT pg_stat_exists_stat('$kind', $dboid, $objoid)"); +} + +sub checkpoint_stats +{ + my %results; + + $results{count} = $node->safe_psql($connect_db, + "SELECT checkpoints_timed + checkpoints_req FROM pg_stat_bgwriter"); + $results{reset} = $node->safe_psql($connect_db, + "SELECT stats_reset FROM pg_stat_bgwriter"); + + return \%results; +} + +sub wal_stats +{ + my %results; + $results{records} = + $node->safe_psql($connect_db, "SELECT wal_records FROM pg_stat_wal"); + $results{bytes} = + $node->safe_psql($connect_db, "SELECT wal_bytes FROM pg_stat_wal"); + $results{reset} = + $node->safe_psql($connect_db, "SELECT stats_reset FROM pg_stat_wal"); + + return \%results; +} -- 2.35.1.677.gabf474a5dd --c4n45bccvxafocvc Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v68-0021-pgstat-test-subscriber-stats-reset-and-drop.patch" ^ permalink raw reply [nested|flat] 4+ messages in thread
* [PATCH v69 16/28] pgstat: test: stats handling of restarts, including crashes. @ 2022-03-20 20:33 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 4+ messages in thread From: Melanie Plageman @ 2022-03-20 20:33 UTC (permalink / raw) Stats should not be restored if the db crashed. Also, ensure invalid stats files are handled gracefully. Author: Melanie Plageman <[email protected]> Author: Andres Freund <[email protected]> Discussion: https://postgr.es/m/[email protected] --- src/test/recovery/t/029_stats_restart.pl | 305 +++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 src/test/recovery/t/029_stats_restart.pl diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl new file mode 100644 index 00000000000..55534b3a68d --- /dev/null +++ b/src/test/recovery/t/029_stats_restart.pl @@ -0,0 +1,305 @@ +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +# Tests statistics handling around restarts, including handling of crashes and +# invalid stats files, as well as restorting stats after "normal" restarts. + +use strict; +use warnings; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; +use File::Copy; + +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init(allows_streaming => 1); +$node->start; +$node->append_conf('postgresql.conf', "track_functions = 'all'"); +$node->reload; + +my $connect_db = 'postgres'; +my $db_under_test = 'test'; + +$node->safe_psql($connect_db, "CREATE DATABASE $db_under_test"); + +# Create table in test db +$node->safe_psql($db_under_test, + "CREATE TABLE tab_stats_crash_discard_test1 AS SELECT generate_series(1,100) AS a" +); + +# Create function in test db +$node->safe_psql($db_under_test, + "CREATE FUNCTION func_stats_crash_discard1() RETURNS VOID AS 'select 2;' LANGUAGE SQL IMMUTABLE" +); + +# collect object oids +my $dboid = $node->safe_psql($db_under_test, + "SELECT oid FROM pg_database WHERE datname = '$db_under_test'"); +my $funcoid = $node->safe_psql($db_under_test, + "SELECT 'func_stats_crash_discard1()'::regprocedure::oid"); +my $tableoid = $node->safe_psql($db_under_test, + "SELECT 'tab_stats_crash_discard_test1'::regclass::oid"); + +# generate stats and flush them +trigger_funcrel_stat(); + +# verify stats objects exist +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Regular shutdown +$node->stop(); + +# Backup stats files +my $statsfile = $PostgreSQL::Test::Utils::tmp_check . '/' . "discard_stats1"; +ok(!-f "$statsfile", "Backup statsfile cannot already exist"); + +my $datadir = $node->data_dir(); +my $og_stats = $datadir . '/' . "pg_stat" . '/' . "pgstat.stat"; +ok(-f "$og_stats", "Origin stats file must exist"); +copy($og_stats, $statsfile) or die "Copy failed: $!"; + +# Start the server +$node->start; + +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Fast shutdown +$node->stop('immediate'); + +ok(!-f "$og_stats", "No stats file should exist after immediate shutdown."); + +# Copy the old stats back to test we discard stats after crash restart +copy($statsfile, $og_stats) or die "Copy failed: $!"; + +# Start the server +$node->start; + +# Stats should have been discarded +is(exists_stat('database', $dboid, 0), + 'f', "Check that db stat does not exist."); +is(exists_stat('function', $dboid, $funcoid), + 'f', "Check that function stat does not exist."); +is(exists_stat('relation', $dboid, $tableoid), + 'f', "Check that relation stat does not exist."); + +# Get rid of backup statsfile +unlink $statsfile or die "cannot unlink $statsfile $!"; + + +# generate new stats and flush them +trigger_funcrel_stat(); + +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Regular shutdown +$node->stop(); + +sub overwrite_file +{ + my ($filename, $str) = @_; + open my $fh, ">", $filename + or die "could not write \"$filename\": $!"; + print $fh $str; + close $fh; + return; +} + +overwrite_file($og_stats, "ZZZZZZZZZZZZZ"); + +# Normal startup and no issues despite invalid stats file +$node->start; + +# No stats present due to invalid stats file +is(exists_stat('database', $dboid, 0), + 'f', "Check that db stat does not exist."); +is(exists_stat('function', $dboid, $funcoid), + 'f', "Check that function stat does not exist."); +is(exists_stat('relation', $dboid, $tableoid), + 'f', "Check that relation stat does not exist."); + + +## Checks related to stats persistency around restarts and resets + +# Ensure enough checkpoints to protect against races for test after reset, +# even on very slow machines. +$node->safe_psql($connect_db, "CHECKPOINT; CHECKPOINT;"); + + +## check checkpoint and wal stats are incremented due to restart + +my $ckpt_start = checkpoint_stats(); +my $wal_start = wal_stats(); +$node->restart; + +my $sect = "post restart"; +my $ckpt_restart = checkpoint_stats(); +my $wal_restart = wal_stats(); + +cmp_ok( + $ckpt_start->{count}, '<', + $ckpt_restart->{count}, + "$sect: increased checkpoint count"); +cmp_ok( + $wal_start->{records}, '<', + $wal_restart->{records}, + "$sect: increased wal record count"); +cmp_ok($wal_start->{bytes}, '<', $wal_restart->{bytes}, + "$sect: increased wal bytes"); +is( $ckpt_start->{reset}, + $ckpt_restart->{reset}, + "$sect: checkpoint stats_reset equal"); +is($wal_start->{reset}, $wal_restart->{reset}, + "$sect: wal stats_reset equal"); + + +## Check that checkpoint stats are reset, WAL stats aren't affected + +$node->safe_psql($connect_db, "SELECT pg_stat_reset_shared('bgwriter')"); + +$sect = "post ckpt reset"; +my $ckpt_reset = checkpoint_stats(); +my $wal_ckpt_reset = wal_stats(); + +cmp_ok($ckpt_restart->{count}, + '>', $ckpt_reset->{count}, "$sect: checkpoint count smaller"); +cmp_ok($ckpt_start->{reset}, 'lt', $ckpt_reset->{reset}, + "$sect: stats_reset newer"); + +cmp_ok( + $wal_restart->{records}, + '<=', + $wal_ckpt_reset->{records}, + "$sect: wal record count not affected by reset"); +is( $wal_start->{reset}, + $wal_ckpt_reset->{reset}, + "$sect: wal stats_reset equal"); + + +## check that checkpoint stats stay reset after restart + +$node->restart; + +$sect = "post ckpt reset & restart"; +my $ckpt_restart_reset = checkpoint_stats(); +my $wal_restart2 = wal_stats(); + +# made sure above there's enough checkpoints that this will be stable even on slow machines +cmp_ok( + $ckpt_restart_reset->{count}, + '<', + $ckpt_restart->{count}, + "$sect: checkpoint still reset"); +is($ckpt_restart_reset->{reset}, + $ckpt_reset->{reset}, "$sect: stats_reset same"); + +cmp_ok( + $wal_ckpt_reset->{records}, + '<', + $wal_restart2->{records}, + "$sect: increased wal record count"); +cmp_ok( + $wal_ckpt_reset->{bytes}, + '<', + $wal_restart2->{bytes}, + "$sect: increased wal bytes"); +is( $wal_start->{reset}, + $wal_restart2->{reset}, + "$sect: wal stats_reset equal"); + + +## check WAL stats stay reset + +$node->safe_psql($connect_db, "SELECT pg_stat_reset_shared('wal')"); + +$sect = "post wal reset"; +my $wal_reset = wal_stats(); + +cmp_ok( + $wal_reset->{records}, '<', + $wal_restart2->{records}, + "$sect: smaller record count"); +cmp_ok( + $wal_reset->{bytes}, '<', + $wal_restart2->{bytes}, + "$sect: smaller bytes"); +cmp_ok( + $wal_reset->{reset}, 'gt', + $wal_restart2->{reset}, + "$sect: newer stats_reset"); + +$node->restart; + +$sect = "post wal reset & restart"; +my $wal_reset_restart = wal_stats(); + +# enough WAL generated during prior tests and initdb to make this not racy +cmp_ok( + $wal_reset_restart->{records}, + '<', + $wal_restart2->{records}, + "$sect: smaller record count"); +cmp_ok( + $wal_reset->{bytes}, '<', + $wal_restart2->{bytes}, + "$sect: smaller bytes"); +cmp_ok( + $wal_reset->{reset}, 'gt', + $wal_restart2->{reset}, + "$sect: newer stats_reset"); + + +$node->stop; +done_testing(); + +sub trigger_funcrel_stat +{ + $node->safe_psql( + $db_under_test, q[ + SELECT * FROM tab_stats_crash_discard_test1; + SELECT func_stats_crash_discard1(); + SELECT pg_stat_force_next_flush();]); +} + +sub exists_stat +{ + my ($kind, $dboid, $objoid) = @_; + + return $node->safe_psql($connect_db, + "SELECT pg_stat_exists_stat('$kind', $dboid, $objoid)"); +} + +sub checkpoint_stats +{ + my %results; + + $results{count} = $node->safe_psql($connect_db, + "SELECT checkpoints_timed + checkpoints_req FROM pg_stat_bgwriter"); + $results{reset} = $node->safe_psql($connect_db, + "SELECT stats_reset FROM pg_stat_bgwriter"); + + return \%results; +} + +sub wal_stats +{ + my %results; + $results{records} = + $node->safe_psql($connect_db, "SELECT wal_records FROM pg_stat_wal"); + $results{bytes} = + $node->safe_psql($connect_db, "SELECT wal_bytes FROM pg_stat_wal"); + $results{reset} = + $node->safe_psql($connect_db, "SELECT stats_reset FROM pg_stat_wal"); + + return \%results; +} -- 2.35.1.677.gabf474a5dd --be3jiks7ge4r32o3 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v69-0017-pgstat-test-subscriber-stats-reset-and-drop.patch" ^ permalink raw reply [nested|flat] 4+ messages in thread
* [PATCH v70 19/27] pgstat: test: stats handling of restarts, including crashes. @ 2022-03-20 20:33 Melanie Plageman <[email protected]> 0 siblings, 0 replies; 4+ messages in thread From: Melanie Plageman @ 2022-03-20 20:33 UTC (permalink / raw) Stats should not be restored if the db crashed. Also, ensure invalid stats files are handled gracefully. Author: Melanie Plageman <[email protected]> Author: Andres Freund <[email protected]> Discussion: https://postgr.es/m/[email protected] --- src/test/recovery/t/029_stats_restart.pl | 305 +++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 src/test/recovery/t/029_stats_restart.pl diff --git a/src/test/recovery/t/029_stats_restart.pl b/src/test/recovery/t/029_stats_restart.pl new file mode 100644 index 00000000000..55534b3a68d --- /dev/null +++ b/src/test/recovery/t/029_stats_restart.pl @@ -0,0 +1,305 @@ +# Copyright (c) 2021-2022, PostgreSQL Global Development Group + +# Tests statistics handling around restarts, including handling of crashes and +# invalid stats files, as well as restorting stats after "normal" restarts. + +use strict; +use warnings; +use PostgreSQL::Test::Cluster; +use PostgreSQL::Test::Utils; +use Test::More; +use File::Copy; + +my $node = PostgreSQL::Test::Cluster->new('primary'); +$node->init(allows_streaming => 1); +$node->start; +$node->append_conf('postgresql.conf', "track_functions = 'all'"); +$node->reload; + +my $connect_db = 'postgres'; +my $db_under_test = 'test'; + +$node->safe_psql($connect_db, "CREATE DATABASE $db_under_test"); + +# Create table in test db +$node->safe_psql($db_under_test, + "CREATE TABLE tab_stats_crash_discard_test1 AS SELECT generate_series(1,100) AS a" +); + +# Create function in test db +$node->safe_psql($db_under_test, + "CREATE FUNCTION func_stats_crash_discard1() RETURNS VOID AS 'select 2;' LANGUAGE SQL IMMUTABLE" +); + +# collect object oids +my $dboid = $node->safe_psql($db_under_test, + "SELECT oid FROM pg_database WHERE datname = '$db_under_test'"); +my $funcoid = $node->safe_psql($db_under_test, + "SELECT 'func_stats_crash_discard1()'::regprocedure::oid"); +my $tableoid = $node->safe_psql($db_under_test, + "SELECT 'tab_stats_crash_discard_test1'::regclass::oid"); + +# generate stats and flush them +trigger_funcrel_stat(); + +# verify stats objects exist +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Regular shutdown +$node->stop(); + +# Backup stats files +my $statsfile = $PostgreSQL::Test::Utils::tmp_check . '/' . "discard_stats1"; +ok(!-f "$statsfile", "Backup statsfile cannot already exist"); + +my $datadir = $node->data_dir(); +my $og_stats = $datadir . '/' . "pg_stat" . '/' . "pgstat.stat"; +ok(-f "$og_stats", "Origin stats file must exist"); +copy($og_stats, $statsfile) or die "Copy failed: $!"; + +# Start the server +$node->start; + +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Fast shutdown +$node->stop('immediate'); + +ok(!-f "$og_stats", "No stats file should exist after immediate shutdown."); + +# Copy the old stats back to test we discard stats after crash restart +copy($statsfile, $og_stats) or die "Copy failed: $!"; + +# Start the server +$node->start; + +# Stats should have been discarded +is(exists_stat('database', $dboid, 0), + 'f', "Check that db stat does not exist."); +is(exists_stat('function', $dboid, $funcoid), + 'f', "Check that function stat does not exist."); +is(exists_stat('relation', $dboid, $tableoid), + 'f', "Check that relation stat does not exist."); + +# Get rid of backup statsfile +unlink $statsfile or die "cannot unlink $statsfile $!"; + + +# generate new stats and flush them +trigger_funcrel_stat(); + +is(exists_stat('database', $dboid, 0), 't', "Check that db stat exists."); +is(exists_stat('function', $dboid, $funcoid), + 't', "Check that function stat exists."); +is(exists_stat('relation', $dboid, $tableoid), + 't', "Check that relation stat exists."); + +# Regular shutdown +$node->stop(); + +sub overwrite_file +{ + my ($filename, $str) = @_; + open my $fh, ">", $filename + or die "could not write \"$filename\": $!"; + print $fh $str; + close $fh; + return; +} + +overwrite_file($og_stats, "ZZZZZZZZZZZZZ"); + +# Normal startup and no issues despite invalid stats file +$node->start; + +# No stats present due to invalid stats file +is(exists_stat('database', $dboid, 0), + 'f', "Check that db stat does not exist."); +is(exists_stat('function', $dboid, $funcoid), + 'f', "Check that function stat does not exist."); +is(exists_stat('relation', $dboid, $tableoid), + 'f', "Check that relation stat does not exist."); + + +## Checks related to stats persistency around restarts and resets + +# Ensure enough checkpoints to protect against races for test after reset, +# even on very slow machines. +$node->safe_psql($connect_db, "CHECKPOINT; CHECKPOINT;"); + + +## check checkpoint and wal stats are incremented due to restart + +my $ckpt_start = checkpoint_stats(); +my $wal_start = wal_stats(); +$node->restart; + +my $sect = "post restart"; +my $ckpt_restart = checkpoint_stats(); +my $wal_restart = wal_stats(); + +cmp_ok( + $ckpt_start->{count}, '<', + $ckpt_restart->{count}, + "$sect: increased checkpoint count"); +cmp_ok( + $wal_start->{records}, '<', + $wal_restart->{records}, + "$sect: increased wal record count"); +cmp_ok($wal_start->{bytes}, '<', $wal_restart->{bytes}, + "$sect: increased wal bytes"); +is( $ckpt_start->{reset}, + $ckpt_restart->{reset}, + "$sect: checkpoint stats_reset equal"); +is($wal_start->{reset}, $wal_restart->{reset}, + "$sect: wal stats_reset equal"); + + +## Check that checkpoint stats are reset, WAL stats aren't affected + +$node->safe_psql($connect_db, "SELECT pg_stat_reset_shared('bgwriter')"); + +$sect = "post ckpt reset"; +my $ckpt_reset = checkpoint_stats(); +my $wal_ckpt_reset = wal_stats(); + +cmp_ok($ckpt_restart->{count}, + '>', $ckpt_reset->{count}, "$sect: checkpoint count smaller"); +cmp_ok($ckpt_start->{reset}, 'lt', $ckpt_reset->{reset}, + "$sect: stats_reset newer"); + +cmp_ok( + $wal_restart->{records}, + '<=', + $wal_ckpt_reset->{records}, + "$sect: wal record count not affected by reset"); +is( $wal_start->{reset}, + $wal_ckpt_reset->{reset}, + "$sect: wal stats_reset equal"); + + +## check that checkpoint stats stay reset after restart + +$node->restart; + +$sect = "post ckpt reset & restart"; +my $ckpt_restart_reset = checkpoint_stats(); +my $wal_restart2 = wal_stats(); + +# made sure above there's enough checkpoints that this will be stable even on slow machines +cmp_ok( + $ckpt_restart_reset->{count}, + '<', + $ckpt_restart->{count}, + "$sect: checkpoint still reset"); +is($ckpt_restart_reset->{reset}, + $ckpt_reset->{reset}, "$sect: stats_reset same"); + +cmp_ok( + $wal_ckpt_reset->{records}, + '<', + $wal_restart2->{records}, + "$sect: increased wal record count"); +cmp_ok( + $wal_ckpt_reset->{bytes}, + '<', + $wal_restart2->{bytes}, + "$sect: increased wal bytes"); +is( $wal_start->{reset}, + $wal_restart2->{reset}, + "$sect: wal stats_reset equal"); + + +## check WAL stats stay reset + +$node->safe_psql($connect_db, "SELECT pg_stat_reset_shared('wal')"); + +$sect = "post wal reset"; +my $wal_reset = wal_stats(); + +cmp_ok( + $wal_reset->{records}, '<', + $wal_restart2->{records}, + "$sect: smaller record count"); +cmp_ok( + $wal_reset->{bytes}, '<', + $wal_restart2->{bytes}, + "$sect: smaller bytes"); +cmp_ok( + $wal_reset->{reset}, 'gt', + $wal_restart2->{reset}, + "$sect: newer stats_reset"); + +$node->restart; + +$sect = "post wal reset & restart"; +my $wal_reset_restart = wal_stats(); + +# enough WAL generated during prior tests and initdb to make this not racy +cmp_ok( + $wal_reset_restart->{records}, + '<', + $wal_restart2->{records}, + "$sect: smaller record count"); +cmp_ok( + $wal_reset->{bytes}, '<', + $wal_restart2->{bytes}, + "$sect: smaller bytes"); +cmp_ok( + $wal_reset->{reset}, 'gt', + $wal_restart2->{reset}, + "$sect: newer stats_reset"); + + +$node->stop; +done_testing(); + +sub trigger_funcrel_stat +{ + $node->safe_psql( + $db_under_test, q[ + SELECT * FROM tab_stats_crash_discard_test1; + SELECT func_stats_crash_discard1(); + SELECT pg_stat_force_next_flush();]); +} + +sub exists_stat +{ + my ($kind, $dboid, $objoid) = @_; + + return $node->safe_psql($connect_db, + "SELECT pg_stat_exists_stat('$kind', $dboid, $objoid)"); +} + +sub checkpoint_stats +{ + my %results; + + $results{count} = $node->safe_psql($connect_db, + "SELECT checkpoints_timed + checkpoints_req FROM pg_stat_bgwriter"); + $results{reset} = $node->safe_psql($connect_db, + "SELECT stats_reset FROM pg_stat_bgwriter"); + + return \%results; +} + +sub wal_stats +{ + my %results; + $results{records} = + $node->safe_psql($connect_db, "SELECT wal_records FROM pg_stat_wal"); + $results{bytes} = + $node->safe_psql($connect_db, "SELECT wal_bytes FROM pg_stat_wal"); + $results{reset} = + $node->safe_psql($connect_db, "SELECT stats_reset FROM pg_stat_wal"); + + return \%results; +} -- 2.35.1.677.gabf474a5dd --vl7on5vfmrsyxmos Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v70-0020-pgstat-test-test-stats-interactions-with-streami.patch" ^ permalink raw reply [nested|flat] 4+ messages in thread
end of thread, other threads:[~2022-03-20 20:33 UTC | newest] Thread overview: 4+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2019-12-11 12:54 [PATCH v25 4/5] Add ALTER INDEX ... ALTER COLLATION ... REFRESH VERSION. Julien Rouhaud <[email protected]> 2022-03-20 20:33 [PATCH v70 19/27] pgstat: test: stats handling of restarts, including crashes. Melanie Plageman <[email protected]> 2022-03-20 20:33 [PATCH v68 20/31] pgstat: test: stats handling of restarts, including crashes. Melanie Plageman <[email protected]> 2022-03-20 20:33 [PATCH v69 16/28] pgstat: test: stats handling of restarts, including crashes. Melanie Plageman <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox