Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Columnar tables cause txid wraparound #192

Closed
amihajlovic opened this issue Nov 6, 2023 · 0 comments · Fixed by #194
Closed

[Bug]: Columnar tables cause txid wraparound #192

amihajlovic opened this issue Nov 6, 2023 · 0 comments · Fixed by #194
Assignees
Labels
bug Something isn't working

Comments

@amihajlovic
Copy link

What's wrong?

(auto)vacuuming columnar tables leave pg_class.relfrozenxid as is and doesn't overwrite it with newer txid value. This eventually causes txid wraparound issue and needs to be resolved by setting a database to single user mode and running vacuum(full) on the problematic tables. Vacuum (full) recreates the table and resets pg_class.relfrozenxid value.
Vacuum (freeze) nor columnar.vacuum don't work in this case.

Heap tables always update pg_class.relfrozenxid when vacuum (freeze) is run.

Tested using docker ghcr.io/hydradatabase/hydra:latest

select extversion  from pg_catalog.pg_extension where extname = 'columnar';
/*
extversion|
----------+
11.1-10   |
*/

Repro steps:

create table x () using columnar;

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x'
;
/*
relfrozenxid|
------------+
737         |
*/
select txid_current(); --increase txid counter
/*
txid_current|
------------+
         738|
*/
vacuum(verbose, freeze) x;
/*
statistics for "x":
storage id: 10000000000
total file size: 16384, total data size: 0
compression rate: 1.00x
total row count: 0, stripe count: 0, average rows per stripe: 0
chunk count: 0, containing data for dropped columns: 0

"x": stopping vacuum due to zero column table
*/
SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x'
;
/*
relfrozenxid|
------------+
737         |
*/
------------------------------------------------------------
create table y () using heap;

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'y'
;
/*
relfrozenxid|
------------+
740         |
*/

select txid_current(); --increase txid counter
/*
txid_current|
------------+
         741|
*/
vacuum(verbose, freeze) y;
/*
aggressively vacuuming "public.y"
table "y": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
*/

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'y'
;
/*
relfrozenxid|
------------+
742         |
*/


------------------------------------------------------------

create table x1 (i int) using columnar;

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x1'
;
/*
relfrozenxid|
------------+
742         |
*/
select txid_current(); --increase txid counter
/*
txid_current|
------------+
         743|
*/
vacuum(verbose, freeze) x1;
/*
statistics for "x1":
storage id: 10000000001
total file size: 16384, total data size: 0
compression rate: 1.00x
total row count: 0, stripe count: 0, average rows per stripe: 0
chunk count: 0, containing data for dropped columns: 0

"x1": stopping vacuum due to empty table
*/
SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x1'
;
/*
relfrozenxid|
------------+
742         |
*/
------------------------------------------------------------
create table y1 (i int) using heap;

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'y1'
;
/*
relfrozenxid|
------------+
740         |
*/

select txid_current(); --increase txid counter
/*
relfrozenxid|
------------+
745         |
*/
vacuum(verbose, freeze) y1;
/*
aggressively vacuuming "public.y1"
table "y1": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
*/

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'y1'
;
/*
relfrozenxid|
------------+
746         |
*/




------------------------------------------------------------

create table x2 (i int) using columnar;
insert into x2(i) values(1);

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x2'
;
/*
relfrozenxid|
------------+
746         |
*/
select txid_current(); --increase txid counter
/*
txid_current|
------------+
         748|
*/
vacuum(verbose, freeze) x2;
/*
statistics for "x2":
storage id: 10000000002
total file size: 24576, total data size: 14
compression rate: 0.36x
total row count: 1, stripe count: 1, average rows per stripe: 1
chunk count: 1, containing data for dropped columns: 0, zstd compressed: 1
*/
SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x2'
;
/*
relfrozenxid|
------------+
746         |
*/
------------------------------------------------------------


------------------------------------------------------------

create table x3 (i int) using columnar;
insert into x3(i) values(1);

SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x3'
;
/*
relfrozenxid|
------------+
750         |
*/
select txid_current(); --increase txid counter
/*
txid_current|
------------+
         752|
*/
select columnar.vacuum('x3'::regclass); 
/*
vacuum|
------+
     0|
*/
SELECT c.relfrozenxid
FROM pg_class AS c 
WHERE oid::regclass::text  = 'x3'
;
/*
relfrozenxid|
------------+
750         |
*/
------------------------------------------------------------

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants