事务回卷问题
问题描述
当事务未能正常回收持续一段时间,库年龄达到上限后。
报错如下,此时数据库还可以访问,但不允许写入:
ERROR: database is not accepting commands to avoid wraparound data loss in database "xxx"
HINT: Stop the postmaster and vacuum that database in single-user mode
可能影响
- 如果CN主节点年龄回卷,那么这个CN主节点会变成只读状态;
- 如果某个DN主节点年龄回卷,那么写入到这个DN主节点数据SQL会报错。
解决步骤
- 执行SQL,检查引起年龄回收问题的库:
SELECT datname, age(datfrozenxid) FROM pg_database where age(datfrozenxid)>200000000;
- 连接年龄回卷的库,执行SQL,检查引起年龄回收问题的表;
SELECT pg_namespace.nspname as schema_name,relname, age(relfrozenxid) as xid_age,
pg_size_pretty(pg_table_size(pg_class.oid)) as table_size
FROM pg_class,pg_namespace
WHERE pg_namespace.oid=pg_class.relnamespace and age(relfrozenxid)>200000000 and
relfrozenxid != 0
order by age(relfrozenxid) desc;
- 控制台停止该节点;
- 手动启动节点(指定报错提示中的数据库)进入单用户模式
postgres --single -D ./ xxx(database)
- 手动执行vacuum或vacuum full回收问题表,如遇到报错,需要先解决相应报错;
- ctrl+d退出单用户模式,控制台启动该节点。
年龄回收冲突问题
问题描述
年龄回收时,报冲突错误,如:
ERROR: tuple cannot be frozen now, please try later xid 802439820 cutoff xid 958123080
committs 25144982436271 RecentDataTs 25144852436271
RecentGlobalXmin 1058123080 RecentGlobalDataXmin 1058123080k
可能影响
表年龄回收失败,长时间可能会导致表膨胀严重,影响性能,甚至会导致事务回卷,节点进入只读状态。
解决步骤
- 先检查并清理一些长事务SQL,长期执行未结束的SQL;
- 执行以下命令,减少年龄差,缩小年龄回收范围:
set vacuum_defer_freeze_min_age to 1000000;
- 再尝试回收。
表元数据错误导致年龄回收失败问题
问题描述
表年龄回收时,报错如下:
ERROR: catalog is missing xx attribute(s) for relid xxx
可能原因
表年龄回收失败,长时间可能会导致表膨胀严重,影响性能,甚至会导致事务回卷,节点进入只读状态。
解决步骤
参考文档先修复元数据不一致问题,然后再尝试回收。
toast表元数据错误导致年龄回收失败问题
问题描述
toast表年龄回收时,报错如下:
ERROR: catalog is missing xx attribute(s) for relid xxx
可能原因
表年龄回收失败,长时间可能会导致表膨胀严重,影响性能,甚至会导致事务回卷,节点进入只读状态。
解决步骤
设置set allow_force_ddl=on;后再尝试回收。
临时表残留导致年龄回收失败问题
问题描述
临时表其它进程无法访问,有残留临时表时,无法手动回收这些临时表年龄。
可能影响
表年龄回收失败,长时间可能会导致表膨胀严重,影响性能,甚至会导致事务回卷,节点进入只读状态。
解决步骤
需要将临时表所属的schema 强制删除,如:
drop schema if exists pg_temp_xx cascade;
操作前需要确认当前无业务访问,所有临时表都可以清理。
template0库年龄回收问题
问题描述
年龄需要回收前,需要先连接template0库,该库默认不可连接,尝试连接会报错:
FATAL: database "template0" is not currently accepting connections
可能影响
template0库有年龄问题需要回收,但template0库不可连接。
解决步骤
- 需要修改为template0库可连接,需要先将teledb用户参数allow_dml_on_datanode修改为on,允许该用户在DN上执行DML语句:
alter role teledb set allow_dml_on_datanode to on;
- 再连接所有CN、DN主节点,将template0修改为可连接:
update pg_database set datallowconn=true where datname='template0';
- 连接需要回收年龄的节点,执行vacuum回收命令。
- 还原设置,连接所有CN、DN主节点,将template0修改为不可连接:
update pg_database set datallowconn=false where datname='template0';
- 还原设置,连接CN主节点,将teledb用户参数allow_dml_on_datanode修改为off:
alter role teledb set allow_dml_on_datanode to off;