迫切模式弥补了惰性模式的缺陷。它会扫描所有页面,检查表中的所有元组,更新相关的系统视图,并在可能时删除不必要的CLOG文件与页面。
当满足以下条件时,会执行迫切模式。
pg_database.datfrozenxid<(OldestXmin-vacuum_freeze_table_age)
在上面的条件中,pg_database.datfrozenxid 是系统视图pg_database 中的列,并保存着每个数据库中最老的已冻结的事务标识。这里我们假设所有pg_database.datfrozenxid的值都是726(14版本中安装新数据库集群之后的初始值)。vacuum_freeze_table_age是配置参数(默认为150 000 000)。
CLOG存储着事务的状态。当更新pg_database.datfrozenxid时,PostgreSQL会尝试删除不必要的CLOG文件。注意,相应的CLOG页面也会被删除。
如下一个例子。如果 CLOG 文件0002中包含最小的 pg_database.datfrozenxid,则可以删除旧文件(0000和0001),因为存储在这些文件中的所有事务在整个数据库集簇中已经被视为冻结了。
pg_database.datfrozenxid与CLOG文件
下面展示了pg_database.datfrozenxid与CLOG文件的实际输出:
postgres=# select datname,datfrozenxid from pg_database ;
datname | datfrozenxid
-----------+--------------
postgres | 726
template1 | 726
template0 | 726
ctsdb | 726
testdb | 726
分别对数据库执行vacuum freeze 或者 vacuum full操作,如下操作后
template1=# select datname,datfrozenxid from pg_database ;
datname | datfrozenxid
-----------+--------------
postgres | 23507022
template1 | 23507028
template0 | 726
ctsdb | 23507026
testdb | 23507028
(5 rows)
再对template0执行冻结时,如下报错,template0 数据库默认是不允许登录的,做freeze报错。
[postgres@db113 pg_xact]$ psql -d template0
psql: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL: database "template0" is not currently accepting connections
[postgres@db113 pg_xact]$ vacuumdb --freeze template0
vacuumdb: error: connection to server on socket "/tmp/.s.PGSQL.5432" failed: FATAL: database "template0" is not currently accepting connections
需要 superuser 执行下更新命令。
postgres=# update pg_database set datallowconn = TRUE where datname = 'template0';
UPDATE 1
postgres=# \q
[postgres@db113 pg_xact]$ vacuumdb --freeze template0
vacuumdb: vacuuming database "template0"
postgres=# select datfrozenxid,datname,age(datfrozenxid),txid_current() from pg_database;
datfrozenxid | datname | age | txid_current
--------------+-----------+-----+--------------
23507022 | postgres | 78 | 23507100
23507028 | template1 | 72 | 23507100
23507026 | ctsdb | 74 | 23507100
23507028 | testdb | 72 | 23507100
23507100 | template0 | 0 | 23507100
之后再对template0 数据库不允许登录
postgres=# update pg_database set datallowconn = FALSE where datname = 'template0';
UPDATE 1
template0允许登录参考 https://blog.csdn.net/ctypyb2002/article/details/108483168
clog移除参考https://www.interdb.jp/pg/pgsql06.html
思考:
如果不对template0进行手动参与,clog文件岂不是永远不会删除了。
clog删除后会出现什么后果