Skip to content
pg_dirtyread

pg_dirtyread

pg_dirtyread : Read dead but unvacuumed rows from table

Overview

ID Extension Package Version Category License Language
5050
pg_dirtyread
pg_dirtyread
2.8
ADMIN
BSD 3-Clause
C
Attribute Has Binary Has Library Need Load Has DDL Relocatable Trusted
--s-d-r
No
Yes
No
Yes
yes
no
Relationships
See Also
pg_orphaned
pg_surgery
pageinspect
pg_visibility
pg_cheat_funcs
amcheck
pg_repack
pg_squeeze

Packages

Type Repo Version PG Major Compatibility Package Pattern Dependencies
EXT
MIXED
2.8
18
17
16
15
14
pg_dirtyread -
RPM
PIGSTY
2.8
18
17
16
15
14
pg_dirtyread_$v -
DEB
PGDG
2.8
18
17
16
15
14
postgresql-$v-dirtyread -
Linux / PG PG18 PG17 PG16 PG15 PG14
el8.x86_64
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
el8.aarch64
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
el9.x86_64
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
el9.aarch64
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
el10.x86_64
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
el10.aarch64
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
PIGSTY 2.8
d12.x86_64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
d12.aarch64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
d13.x86_64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
d13.aarch64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
u22.x86_64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
u22.aarch64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
u24.x86_64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
u24.aarch64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
u26.x86_64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
u26.aarch64
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
PGDG 2.8
Package Version OS ORG SIZE File URL
pg_dirtyread_18 2.8 el8.x86_64 pigsty 17.1 KiB pg_dirtyread_18-2.8-1PIGSTY.el8.x86_64.rpm
pg_dirtyread_18 2.7 el8.x86_64 pgdg 17.0 KiB pg_dirtyread_18-2.7-4PGDG.rhel8.x86_64.rpm
pg_dirtyread_18 2.8 el8.aarch64 pigsty 17.2 KiB pg_dirtyread_18-2.8-1PIGSTY.el8.aarch64.rpm
pg_dirtyread_18 2.7 el8.aarch64 pgdg 16.9 KiB pg_dirtyread_18-2.7-4PGDG.rhel8.aarch64.rpm
pg_dirtyread_18 2.8 el9.x86_64 pigsty 17.1 KiB pg_dirtyread_18-2.8-1PIGSTY.el9.x86_64.rpm
pg_dirtyread_18 2.7 el9.x86_64 pgdg 17.3 KiB pg_dirtyread_18-2.7-6PGDG.rhel9.8.x86_64.rpm
pg_dirtyread_18 2.8 el9.aarch64 pigsty 16.9 KiB pg_dirtyread_18-2.8-1PIGSTY.el9.aarch64.rpm
pg_dirtyread_18 2.7 el9.aarch64 pgdg 16.9 KiB pg_dirtyread_18-2.7-6PGDG.rhel9.8.aarch64.rpm
pg_dirtyread_18 2.8 el10.x86_64 pigsty 17.3 KiB pg_dirtyread_18-2.8-1PIGSTY.el10.x86_64.rpm
pg_dirtyread_18 2.7 el10.x86_64 pgdg 17.6 KiB pg_dirtyread_18-2.7-6PGDG.rhel10.2.x86_64.rpm
pg_dirtyread_18 2.8 el10.aarch64 pigsty 17.2 KiB pg_dirtyread_18-2.8-1PIGSTY.el10.aarch64.rpm
pg_dirtyread_18 2.7 el10.aarch64 pgdg 17.3 KiB pg_dirtyread_18-2.7-6PGDG.rhel10.2.aarch64.rpm
postgresql-18-dirtyread 2.8 d12.x86_64 pgdg 21.1 KiB postgresql-18-dirtyread_2.8-1.pgdg12+1_amd64.deb
postgresql-18-dirtyread 2.7 d12.x86_64 pgdg 21.1 KiB postgresql-18-dirtyread_2.7-3.pgdg12+1_amd64.deb
postgresql-18-dirtyread 2.8 d12.aarch64 pgdg 20.9 KiB postgresql-18-dirtyread_2.8-1.pgdg12+1_arm64.deb
postgresql-18-dirtyread 2.7 d12.aarch64 pgdg 20.9 KiB postgresql-18-dirtyread_2.7-3.pgdg12+1_arm64.deb
postgresql-18-dirtyread 2.8 d13.x86_64 pgdg 21.1 KiB postgresql-18-dirtyread_2.8-1.pgdg13+1_amd64.deb
postgresql-18-dirtyread 2.7 d13.x86_64 pgdg 21.1 KiB postgresql-18-dirtyread_2.7-3.pgdg13+1_amd64.deb
postgresql-18-dirtyread 2.8 d13.aarch64 pgdg 21.0 KiB postgresql-18-dirtyread_2.8-1.pgdg13+1_arm64.deb
postgresql-18-dirtyread 2.7 d13.aarch64 pgdg 20.9 KiB postgresql-18-dirtyread_2.7-3.pgdg13+1_arm64.deb
postgresql-18-dirtyread 2.8 u22.x86_64 pgdg 22.0 KiB postgresql-18-dirtyread_2.8-1.pgdg22.04+1_amd64.deb
postgresql-18-dirtyread 2.7 u22.x86_64 pgdg 22.0 KiB postgresql-18-dirtyread_2.7-3.pgdg22.04+1_amd64.deb
postgresql-18-dirtyread 2.8 u22.aarch64 pgdg 21.5 KiB postgresql-18-dirtyread_2.8-1.pgdg22.04+1_arm64.deb
postgresql-18-dirtyread 2.7 u22.aarch64 pgdg 21.4 KiB postgresql-18-dirtyread_2.7-3.pgdg22.04+1_arm64.deb
postgresql-18-dirtyread 2.8 u24.x86_64 pgdg 21.2 KiB postgresql-18-dirtyread_2.8-1.pgdg24.04+1_amd64.deb
postgresql-18-dirtyread 2.7 u24.x86_64 pgdg 21.2 KiB postgresql-18-dirtyread_2.7-3.pgdg24.04+1_amd64.deb
postgresql-18-dirtyread 2.8 u24.aarch64 pgdg 20.9 KiB postgresql-18-dirtyread_2.8-1.pgdg24.04+1_arm64.deb
postgresql-18-dirtyread 2.7 u24.aarch64 pgdg 20.9 KiB postgresql-18-dirtyread_2.7-3.pgdg24.04+1_arm64.deb
postgresql-18-dirtyread 2.8 u26.x86_64 pgdg 20.9 KiB postgresql-18-dirtyread_2.8-1.pgdg26.04+1_amd64.deb
postgresql-18-dirtyread 2.7 u26.x86_64 pgdg 21.3 KiB postgresql-18-dirtyread_2.7-3.pgdg26.04+1_amd64.deb
postgresql-18-dirtyread 2.8 u26.aarch64 pgdg 20.5 KiB postgresql-18-dirtyread_2.8-1.pgdg26.04+1_arm64.deb
postgresql-18-dirtyread 2.7 u26.aarch64 pgdg 20.8 KiB postgresql-18-dirtyread_2.7-3.pgdg26.04+1_arm64.deb

Source

pig build pkg pg_dirtyread;		# build rpm

Install

Make sure PGDG and PIGSTY repo available:

pig repo add pgsql -u   # add both repo and update cache

Install this extension with pig:

pig install pg_dirtyread;		# install via package name, for the active PG version

pig install pg_dirtyread -v 18;   # install for PG 18
pig install pg_dirtyread -v 17;   # install for PG 17
pig install pg_dirtyread -v 16;   # install for PG 16
pig install pg_dirtyread -v 15;   # install for PG 15
pig install pg_dirtyread -v 14;   # install for PG 14

Create this extension with:

CREATE EXTENSION pg_dirtyread;

Usage

Sources: upstream README, Debian changelog, tags.

pg_dirtyread reads dead or updated heap rows that have not yet been vacuumed away. The function returns record, so every call needs a table alias that declares the columns you want back.

Basic Usage

CREATE EXTENSION pg_dirtyread;

SELECT *
FROM pg_dirtyread('foo') AS t(bar bigint, baz text);

Columns are matched by name, so the alias can omit columns or place them in a different order.

Example

CREATE TABLE foo (bar bigint, baz text);
ALTER TABLE foo SET (autovacuum_enabled = false, toast.autovacuum_enabled = false);

INSERT INTO foo VALUES (1, 'Test'), (2, 'New Test');
DELETE FROM foo WHERE bar = 1;

SELECT * FROM pg_dirtyread('foo') AS t(bar bigint, baz text);

The deleted row can remain visible until vacuum removes it.

Dropped Columns

Dropped column contents can be retrieved as long as the table has not been rewritten by operations such as VACUUM FULL or CLUSTER. Use dropped_N, where N is the original 1-based column position:

CREATE TABLE ab(a text, b text);
INSERT INTO ab VALUES ('Hello', 'World');
ALTER TABLE ab DROP COLUMN b;
DELETE FROM ab;

SELECT *
FROM pg_dirtyread('ab') AS ab(a text, dropped_2 text);

Only limited type checks are possible because PostgreSQL removes the dropped column’s original type metadata.

System Columns

Include system columns in the alias to retrieve them. A special dead boolean column reports rows that are surely dead:

SELECT *
FROM pg_dirtyread('foo') AS t(
  tableoid oid,
  ctid tid,
  xmin xid,
  xmax xid,
  cmin cid,
  cmax cid,
  dead boolean,
  bar bigint,
  baz text
);

The dead column is not usable during recovery, including on standby servers. The oid system column is only available on PostgreSQL 11 and earlier.

Caveats

  • Pigsty packages pg_dirtyread 2.8 as RPMs for PostgreSQL 14-18; DEB availability comes from PGDG as postgresql-$v-dirtyread.
  • Upstream 2.8 is a PostgreSQL 19 compatibility release for the default TOAST compression change to lz4; no new user-facing SQL function is documented.
  • pg_dirtyread is for forensic and recovery-style inspection. It bypasses normal MVCC visibility expectations and should not be used for application reads.
Last updated on