• PostgreSQL中的Toast Pointer


    1、分析背景

      在使用数据库的过程中(PG的版本为9.2),遇到了错误"missing chunk number 0 for toast value XX in pg_toast_2619"。根据错误描述,猜测原因可能是:主表字段还留存着Toast Pointer,但Toast表中已经没有对应的Chunk条目。证明这个猜测的关键,是根据主表字段的Toast Pointer,去找Toast Pointer所指向的Chunk条目是否存在。自然,读懂(解析)Toast Pointer就是分析的第一步,但我查阅了大量资料后却没有找到直接解析Toast Pointer的方法,只好自己尝试去分析。本文就是要探索Toast Pointer解析的方法,并对Toast Pointer的结构进行说明。

      在分析之前,先说明主表与Toast表的组织关系,如下图:

    2、分析方法

    分析思想:通过对数据内容的分析,反向推演数据的结构。

    分析方法:制造数据得到一个真实的Toast Pointer,通过对Toast Pointer二进制表达的分析,确定Toast Pointer由哪几部分组成以及各部分的含义,并加以证明。

    3、分析过程

    基于上述分析方法,分析过程如下:

    1)安装pageinspect扩展

    借助该扩展,可查看page中各结构体的数值,以及tuple(行)的Raw值(得到Toast Pointer必须查看RAW值,因为通过SQL来查询B字段,将得到Toast Pointer所指向的value,而不是B字段存储的Toast Pointer)。

    2)制作测试数据

        创建了测试表t,向表t的col字段插入了长度为3808的字符串。col字段的存储类型为"extended",说明会首先压缩,如果压缩后仍然超过TOAST_TUPLE_THRESHOLD(一般为2K),将使用Toast表。

    3)检查Toast是否启用

        表t对应的Toast表OID为27132,表名为pg_toast_27129。

        pg_toast_27129的大小不为0,说明在该例中启用了Toast表。

    4)检查col字段是否启用了压缩

        col字段的字符个数为3808,但存储仅占用了2763字节,说明col字段启用了压缩。该现象与col字段的存储类型"extend"一致。

    5)查看pg_toast_27129表中的chunk条目

        col字段中的字符串被分成2个chunk,即在Toast表中有2个chunk条目。2个chunk条目长度合计值为2763,与上一步压缩后的存储字节数一致。

    6)得到col字段的RAW值

        使用pageinspect扩展的get_raw_page、heap_page_items函数,得到表t唯一一条记录的row value(即t_data)值,该row value也是唯一的一个字段col在内存中的二进制表达。

        在pg的官方文档中,对Toast有这样的一段描述:

        从上文选中部分可知,Toast Pointer的大小为18字节,包括变长标头、字段值实际长度、字段值逻辑长度、Toast表OID、Toast Chunk OID 共5个部分。OID一般占用4字节,我们从t_data的最右边分析起,先取4个字节0xfc690000。由于X86架构下,使用小端存储,因此内存中的0xfc690000,实际的字节序为0x000069fc,将其转换为10进制数值

        而27132,正是Toast表的OID:

        因此,最右边4个字节代表Toast表的OID。

     继续取下一个4字节0xff690000,转换为10进制数值:

        而27135,正是Chunk的OID:

        因此靠右的5-8字节代表Chunk的OID。

        继续取下一个4字节0xcb0a0000,转换为10进制数值:

        而2763,正是col字段的逻辑长度(压缩后的长度):

        因此靠右的9-12字节代表字段值的逻辑长度。

        继续取下一个4字节0xe40e0000,转换为10进制数值:

        而3812,正是col字段实际长度3808+4(表示实际长度所占用的4字节):

     因此靠右的13-16字节代表字段值的实际长度(包括表示长度的4字节自身)。

        至于最后的2字节0x0112,以不同的值插入时,这两个字节的内容是不变的。暂时没有分析清楚这两个字节所代表的含义。

     4、分析结论

      综上分析,Toast Pointer的大小由18字节、5部分组成,分别是:

      字节流(从左往右)

    含义

    1-2

    不详

    3-6

    字段值的实际长度

    7-10

    字段值的逻辑长度

    11-14

    Chunk号,即Chunk_id

    15-16

    Toast表的OID

      如果遇到了"missing chunk number 0 for toast value XX in pg_toast_2619 "错误,可通过如下方法进行验证:

      1)通过上文的方法得到某行某列值的Toast Pointer

      2)再从Toast Pointer中解析得到Toast表的OID(这个从pg_class中也可以得到)、Chunk号,

      3)去Toast表中查询是否存在该Chunk_id对应的条目。

  • 相关阅读:
    读取IIS用户名和密码VBS代码
    sqltools最新增强版
    网站后台备份自动备份成ASA格式却并不表示拿Shell方法
    Google Hack 最新版
    FZU 2105 Digits Count(AC)
    ZOJ 1387 Decoding Morse Sequences
    ZOJ 1391 Horizontally Visible Segments
    codeforces Round #184 Div.2 B Continued Fractions
    FZU 2105 Digits Count(WA)
    POJ 2828 Buy Tickets
  • 原文地址:https://www.cnblogs.com/6yuhang/p/12045666.html
Copyright © 2020-2023  润新知