使用索引时出现index … contains unexpected zero page at block …故障 ¶
直接原因:
在使用索引时,读入内存中的页面为全零页面。
间接原因:
由于硬件系统的原因导致写入外存中的页面或者是读入内存中的页面为全零页面,下面将通过实际举例展示如何查看全零页面。
查看目标索引是否成功创建
test=# \di
创建并使用pageinspect插件(插件的具体使用方法详见KingbaseES插件参考手册pageinspect)查看内存buff中读入的页面是否为全零页面
test=# CREATE EXTENSION pageinspect; SELECT get_raw_page::text FROM get_raw_page('index', 1);其中’index’为目标索引,1为要查看的内存中的页号,页面号的值可以在错误信息中找到。
如果上述步骤读入内存中的页面是全零页面,那么记录下页面号,找到目标索引的relfilenode再通过relfilenode找到目标索引在data目录下的位置,然后使用Linux命令hexdump查看外存中索引文件中的目标页面并确认目标页面是否在写入外存时就已经发生损坏变成全零页面
以下将分步展示查看外存页面的步骤:
3.1. 计算段号segNo
segNo = pageNo * pageSize / segSize(注:结果向下取整)
在上述公式中segNo代表着段号,在KingBaseES中数据是存储在一个或多个文件中的,每一个保存数据的文件被称为段,段号就代表了存放页面的文件的序号。
pageNo代表了页面号,页面号在报错信息中记录。
pageSize代表了页面大小,可以通过下面的命令获取它的值:
..code:
test=# show block_size; block_size ------------ 8192segSize代表的是段容量,每个段的容量大小是固定的1048576KB。
3.2. 计算起始地址start
start = pageNo * pageSize - segNo * segSize
由于在外存中数据是通过文件的形式存储的,所以你需要使用hexdump命令查看目标文件,但是在一个文件中又存储了大量的页面,为了只看你关心的目标页面,你需要计算该页面的起始地址。
3.3. 找到目标文件
test=# SELECT relfilenode,relname FROM pg_class;在得到必要的参数后下一步就是需要找到你要查看的文件,文件在路径 bin/base/目标数据库oid/ 下,使用以上示例命令,通过观察relname可以找到你要查看的索引的relfilenode。
文件的命名方式为relfilenode.segNo,但是有一种特殊情况就是当段号为0时文件仅以relfilenode命名。
例如文件13521就是relfilenode为13521的第0段文件,而文件13521.2就是relfilenode为13521的第2段文件。
3.4. 查看目标文件
查看文件需要使用Linux的hexdump命令,命令的格式为:hexdump -s start -n pageSize filename
在上述命令中<-s start>代表了文件的起始地址。
<-n pageSize>代表了输出的内容的大小,由于你只需要看一个页面所以只需要输出一个页面的大小就可以。
示例:
hexdump -s 8192 -n 8192 16426上述示例的含义为我要查看文件16426从8192地址开始往后8KB的内容。
最后确认上述结果后在kingbase.conf中配置trace_mdwrite参数为on,trace_mdwrite_level参数为all,重新创建索引再查看sys_log日志
trace_mdwrite_level参数有三个级别分别为valid、non-zero、all,代表含义分别为追踪无效页面,追踪全零页面,追踪无效页面和全零页面。
将trace_mdwrite_level参数置为all则可以保证创建索引时系统写入的页面的页头既有效又不为全零,如果二者之中有一个条件不符合,那么在sys_log文件中将存在相应的日志记录。
在查看日志发现没有相应日志记录之后再次执行上述步骤,确定是在写入外存还是在读入内存时发生页面出现全零现象。
根本原因:
存储数据的磁盘受损,应当考虑更换磁盘重启数据库服务器,重新创建索引,再次尝试使用。
为避免页面受损出现全零页面应当保证做出以下要求:
使用可靠的数据存储磁盘。
完善灾备系统对数据做好充分地备份,以减少甚至避免硬件故障产生的损失。