mirror of https://github.com/citusdata/citus.git
Columnar: fix wraparound bug. (#5962)
columnar_vacuum_rel() now advances relfrozenxid.
Fixes #5958.
(cherry picked from commit 74ce210f8b
)
pull/5977/head
parent
6663635593
commit
4c2f22d9fa
|
@ -390,7 +390,7 @@ jobs:
|
||||||
when: on_fail
|
when: on_fail
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
name: 'Save tap logs'
|
name: 'Save tap logs'
|
||||||
path: /home/circleci/project/src/test/recovery/tmp_check/log
|
path: /home/circleci/project/src/test/<< parameters.suite >>/tmp_check/log
|
||||||
when: on_fail
|
when: on_fail
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
name: 'Save core dumps'
|
name: 'Save core dumps'
|
||||||
|
@ -533,6 +533,12 @@ workflows:
|
||||||
image_tag: '12.8'
|
image_tag: '12.8'
|
||||||
suite: recovery
|
suite: recovery
|
||||||
requires: [build-12]
|
requires: [build-12]
|
||||||
|
- tap-test-citus:
|
||||||
|
name: 'test-12_tap-columnar-freezing'
|
||||||
|
pg_major: 12
|
||||||
|
image_tag: '12.8'
|
||||||
|
suite: columnar_freezing
|
||||||
|
requires: [build-12]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-12_check-failure'
|
name: 'test-12_check-failure'
|
||||||
pg_major: 12
|
pg_major: 12
|
||||||
|
@ -607,6 +613,12 @@ workflows:
|
||||||
image_tag: '13.4'
|
image_tag: '13.4'
|
||||||
suite: recovery
|
suite: recovery
|
||||||
requires: [build-13]
|
requires: [build-13]
|
||||||
|
- tap-test-citus:
|
||||||
|
name: 'test-13_tap-columnar-freezing'
|
||||||
|
pg_major: 13
|
||||||
|
image_tag: '13.4'
|
||||||
|
suite: columnar_freezing
|
||||||
|
requires: [build-13]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-13_check-failure'
|
name: 'test-13_check-failure'
|
||||||
pg_major: 13
|
pg_major: 13
|
||||||
|
@ -681,6 +693,12 @@ workflows:
|
||||||
image_tag: '14.0'
|
image_tag: '14.0'
|
||||||
suite: recovery
|
suite: recovery
|
||||||
requires: [build-14]
|
requires: [build-14]
|
||||||
|
- tap-test-citus:
|
||||||
|
name: 'test-14_tap-columnar-freezing'
|
||||||
|
pg_major: 14
|
||||||
|
image_tag: '14.0'
|
||||||
|
suite: columnar_freezing
|
||||||
|
requires: [build-14]
|
||||||
- test-citus:
|
- test-citus:
|
||||||
name: 'test-14_check-failure'
|
name: 'test-14_check-failure'
|
||||||
pg_major: 14
|
pg_major: 14
|
||||||
|
|
|
@ -1018,6 +1018,27 @@ NeededColumnsList(TupleDesc tupdesc, Bitmapset *attr_needed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ColumnarTableTupleCount returns the number of tuples that columnar
|
||||||
|
* table with relationId has by using stripe metadata.
|
||||||
|
*/
|
||||||
|
static uint64
|
||||||
|
ColumnarTableTupleCount(Relation relation)
|
||||||
|
{
|
||||||
|
List *stripeList = StripesForRelfilenode(relation->rd_node);
|
||||||
|
uint64 tupleCount = 0;
|
||||||
|
|
||||||
|
ListCell *lc = NULL;
|
||||||
|
foreach(lc, stripeList)
|
||||||
|
{
|
||||||
|
StripeMetadata *stripe = lfirst(lc);
|
||||||
|
tupleCount += stripe->rowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tupleCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* columnar_vacuum_rel implements VACUUM without FULL option.
|
* columnar_vacuum_rel implements VACUUM without FULL option.
|
||||||
*/
|
*/
|
||||||
|
@ -1034,6 +1055,9 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pgstat_progress_start_command(PROGRESS_COMMAND_VACUUM,
|
||||||
|
RelationGetRelid(rel));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If metapage version of relation is older, then we hint users to VACUUM
|
* If metapage version of relation is older, then we hint users to VACUUM
|
||||||
* the relation in ColumnarMetapageCheckVersion. So if needed, upgrade
|
* the relation in ColumnarMetapageCheckVersion. So if needed, upgrade
|
||||||
|
@ -1057,6 +1081,79 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
|
||||||
{
|
{
|
||||||
TruncateColumnar(rel, elevel);
|
TruncateColumnar(rel, elevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RelationOpenSmgr(rel);
|
||||||
|
BlockNumber new_rel_pages = smgrnblocks(rel->rd_smgr, MAIN_FORKNUM);
|
||||||
|
|
||||||
|
/* get the number of indexes */
|
||||||
|
List *indexList = RelationGetIndexList(rel);
|
||||||
|
int nindexes = list_length(indexList);
|
||||||
|
|
||||||
|
TransactionId oldestXmin;
|
||||||
|
TransactionId freezeLimit;
|
||||||
|
MultiXactId multiXactCutoff;
|
||||||
|
|
||||||
|
/* initialize xids */
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_15
|
||||||
|
MultiXactId oldestMxact;
|
||||||
|
vacuum_set_xid_limits(rel,
|
||||||
|
params->freeze_min_age,
|
||||||
|
params->freeze_table_age,
|
||||||
|
params->multixact_freeze_min_age,
|
||||||
|
params->multixact_freeze_table_age,
|
||||||
|
&oldestXmin, &oldestMxact,
|
||||||
|
&freezeLimit, &multiXactCutoff);
|
||||||
|
|
||||||
|
Assert(MultiXactIdPrecedesOrEquals(multiXactCutoff, oldestMxact));
|
||||||
|
#else
|
||||||
|
TransactionId xidFullScanLimit;
|
||||||
|
MultiXactId mxactFullScanLimit;
|
||||||
|
vacuum_set_xid_limits(rel,
|
||||||
|
params->freeze_min_age,
|
||||||
|
params->freeze_table_age,
|
||||||
|
params->multixact_freeze_min_age,
|
||||||
|
params->multixact_freeze_table_age,
|
||||||
|
&oldestXmin, &freezeLimit, &xidFullScanLimit,
|
||||||
|
&multiXactCutoff, &mxactFullScanLimit);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Assert(TransactionIdPrecedesOrEquals(freezeLimit, oldestXmin));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Columnar storage doesn't hold any transaction IDs, so we can always
|
||||||
|
* just advance to the most aggressive value.
|
||||||
|
*/
|
||||||
|
TransactionId newRelFrozenXid = oldestXmin;
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_15
|
||||||
|
MultiXactId newRelminMxid = oldestMxact;
|
||||||
|
#else
|
||||||
|
MultiXactId newRelminMxid = multiXactCutoff;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double new_live_tuples = ColumnarTableTupleCount(rel);
|
||||||
|
|
||||||
|
/* all visible pages are always 0 */
|
||||||
|
BlockNumber new_rel_allvisible = 0;
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_15
|
||||||
|
bool frozenxid_updated;
|
||||||
|
bool minmulti_updated;
|
||||||
|
|
||||||
|
vac_update_relstats(rel, new_rel_pages, new_live_tuples,
|
||||||
|
new_rel_allvisible, nindexes > 0,
|
||||||
|
newRelFrozenXid, newRelminMxid,
|
||||||
|
&frozenxid_updated, &minmulti_updated, false);
|
||||||
|
#else
|
||||||
|
vac_update_relstats(rel, new_rel_pages, new_live_tuples,
|
||||||
|
new_rel_allvisible, nindexes > 0,
|
||||||
|
newRelFrozenXid, newRelminMxid, false);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pgstat_report_vacuum(RelationGetRelid(rel),
|
||||||
|
rel->rd_rel->relisshared,
|
||||||
|
Max(new_live_tuples, 0),
|
||||||
|
0);
|
||||||
|
pgstat_progress_end_command();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Makefile for src/test/columnar_freezing
|
||||||
|
#
|
||||||
|
# Test that columnar freezing works.
|
||||||
|
#
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
subdir = src/test/columnar_freezing
|
||||||
|
top_builddir = ../../..
|
||||||
|
include $(top_builddir)/Makefile.global
|
||||||
|
|
||||||
|
# copied from pgxs/Makefile.global to use postgres' abs build dir for pg_regress
|
||||||
|
ifeq ($(enable_tap_tests),yes)
|
||||||
|
|
||||||
|
define citus_prove_installcheck
|
||||||
|
rm -rf '$(CURDIR)'/tmp_check
|
||||||
|
$(MKDIR_P) '$(CURDIR)'/tmp_check
|
||||||
|
cd $(srcdir) && \
|
||||||
|
TESTDIR='$(CURDIR)' \
|
||||||
|
PATH="$(bindir):$$PATH" \
|
||||||
|
PGPORT='6$(DEF_PGPORT)' \
|
||||||
|
top_builddir='$(CURDIR)/$(top_builddir)' \
|
||||||
|
PG_REGRESS='$(pgxsdir)/src/test/regress/pg_regress' \
|
||||||
|
TEMP_CONFIG='$(CURDIR)'/postgresql.conf \
|
||||||
|
$(PROVE) $(PG_PROVE_FLAGS) $(PROVE_FLAGS) $(if $(PROVE_TESTS),$(PROVE_TESTS),t/*.pl)
|
||||||
|
endef
|
||||||
|
|
||||||
|
else
|
||||||
|
citus_prove_installcheck = @echo "TAP tests not enabled when postgres was compiled"
|
||||||
|
endif
|
||||||
|
|
||||||
|
installcheck:
|
||||||
|
$(citus_prove_installcheck)
|
||||||
|
|
||||||
|
clean distclean maintainer-clean:
|
||||||
|
rm -rf tmp_check
|
|
@ -0,0 +1,7 @@
|
||||||
|
shared_preload_libraries=citus
|
||||||
|
shared_preload_libraries='citus'
|
||||||
|
vacuum_freeze_min_age = 50000
|
||||||
|
vacuum_freeze_table_age = 50000
|
||||||
|
synchronous_commit = off
|
||||||
|
fsync = off
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Minimal test testing streaming replication
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use PostgresNode;
|
||||||
|
use TestLib;
|
||||||
|
use Test::More tests => 2;
|
||||||
|
|
||||||
|
# Initialize single node
|
||||||
|
my $node_one = get_new_node('node_one');
|
||||||
|
$node_one->init();
|
||||||
|
$node_one->start;
|
||||||
|
|
||||||
|
# initialize the citus extension
|
||||||
|
$node_one->safe_psql('postgres', "CREATE EXTENSION citus;");
|
||||||
|
|
||||||
|
# create columnar table and insert simple data to verify the data survives a crash
|
||||||
|
$node_one->safe_psql('postgres', "
|
||||||
|
CREATE TABLE test_row(i int);
|
||||||
|
INSERT INTO test_row VALUES (1);
|
||||||
|
CREATE TABLE test_columnar_freeze(i int) USING columnar WITH(autovacuum_enabled=false);
|
||||||
|
INSERT INTO test_columnar_freeze VALUES (1);
|
||||||
|
");
|
||||||
|
|
||||||
|
my $ten_thousand_updates = "";
|
||||||
|
|
||||||
|
foreach (1..10000) {
|
||||||
|
$ten_thousand_updates .= "UPDATE test_row SET i = i + 1;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
# 70K updates
|
||||||
|
foreach (1..7) {
|
||||||
|
$node_one->safe_psql('postgres', $ten_thousand_updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $result = $node_one->safe_psql('postgres', "
|
||||||
|
select age(relfrozenxid) < 70000 as was_frozen
|
||||||
|
from pg_class where relname='test_columnar_freeze';
|
||||||
|
");
|
||||||
|
print "node one count: $result\n";
|
||||||
|
is($result, qq(f), 'columnar table was not frozen');
|
||||||
|
|
||||||
|
$node_one->safe_psql('postgres', 'VACUUM FREEZE test_columnar_freeze;');
|
||||||
|
|
||||||
|
$result = $node_one->safe_psql('postgres', "
|
||||||
|
select age(relfrozenxid) < 70000 as was_frozen
|
||||||
|
from pg_class where relname='test_columnar_freeze';
|
||||||
|
");
|
||||||
|
print "node one count: $result\n";
|
||||||
|
is($result, qq(t), 'columnar table was frozen');
|
||||||
|
|
||||||
|
$node_one->stop('fast');
|
||||||
|
|
Loading…
Reference in New Issue