事务状态访问异常 ¶
常见报错:
could not access status of transaction xxxx could not open file "sys_xact/xxxx": No such file or directory
信息查看与梳理:
在ksql中show block_size;查看页面大小。
-
单机环境
查找kingbase日志,以及逻辑备份日志,找到最早报该错误的时间点;
-
集群环境
查找集群中所有节点的kingbase日志,以及逻辑备份日志,找到最早报该错误的时间点;
根据集群中所有节点的kbha.log日志、hamgr.log日志梳理出问题前后集群状态变化情况;
常见原因:
-
xact不正常情况
a). 新xact文件丢失
排查思路:
(1). sys_controldata data目录 | grep NextXID 查看下一个事务id;
(2). 报错的事务id与NextXID对比,如果相差很大,则不是新xact文件丢失问题;
(3). 如果相差比较小的话,如果小于128*block_size,则报错的事务id在当前正在写入的xact日志段中,需要排查操作系统日志,是否有存储或内存方面的报错;
b). 旧xact文件被异常清理
排查思路:
(1). 丢失xact文件的前后文件均存在,可以查找存储是否有异常信息;
(2). 如若存储没有异常,则将相关情况反馈给研发定位分析;
-
xact正常情况
a). 被frozen的数据元组使用xid判断可见性
排查思路:
(1). 定位报错时正在操作的表对象
1). 查看kingbase或逻辑备份日志,找最早报错执行的sql并找出sql中所涉及的表对象;
2). set synchronize_seqscans to off;
3). 通过select xmin, xmax, ctid, *from的查询方式来定位具体是哪个表的问题;
(2). 系统表查询
select relfrozenxid from sys_class where relname = '定位的表对象';
(3). 查看具体page页中的元组头信息
1). 创建pageinspcet插件;
2). 通过(1)中知道具体是在查询哪一行后报了错,来确定报错的这一行的ctid值; (比如(1)中最后能查到的一行元组的ctid为(X,Y),则报错的元组的ctid的页面号可能为X或者X+1)
3). select t_infomask, * from heap_page_items(get_raw_page('报错的表对象', 页面号)) where t_xmin = xxxx;
4). select 查询到的t_infomask & 768;
如果为768,则该tuple有被设置frozen标志;否则,没有。
5). 如果是集群环境,排查所有节点的hamgr.log日志,查看主库是否对最早出问题的节点执行过多次故障恢复,是否有多次rewind成功,但起库失败的情况;
将以上收集的信息,提供给研发,以便接着分析;
b). 数据损坏导致xid异常
排查思路:
(1). 使用for i in {1..N}; do printf '125'; done > xxxx 造丢失的xact文件;(N为32*block_size)
(2). 定位到的出错表的数据可以正常读取,则不是数据损坏的问题;如果不能正常读取,则需要借助备份重做数据;