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对应的条目。

PostgreSQL中的Toast Pointer的更多相关文章

  1. 通过arcgis在PostgreSQL中创建企业级地理数据库

    部署环境: Win7 64位旗舰版 软件版本: PostgreSQL-9.1.3-2-windows-x64 Postgis-pg91x64-setup-2.0.6-1 Arcgis 10.1 SP1 ...

  2. css鼠标手型cursor中hand与pointer

    css鼠标手型cursor中hand与pointer Example:CSS鼠标手型效果 <a href="#" style="cursor:hand"& ...

  3. Win 10 开发中Adaptive磁贴模板的XML文档结构,Win10 应用开发中自适应Toast通知的XML文档结构

    分享两篇Win 10应用开发的XML文档结构:Win 10 开发中Adaptive磁贴模板的XML文档结构,Win10 应用开发中自适应Toast通知的XML文档结构. Win 10 开发中Adapt ...

  4. 如何在子线程中使用Toast和更新UI

    因为没一个Looper处理消息循环,所以子线程中无法使用Toast 方法: Looper.prepare(); Toast.makeText(getActivity(),"刷到底啦" ...

  5. Android学习笔记----TimerTask中显示Toast的问题

    今天想在TimerTask的run函数中调用Toast显示一下提示信息,却总是导致程序崩溃.可是try语句块却又无法捕获到异常,代码如下: ...... Timer timer = new Timer ...

  6. PostgreSQL 中日期类型转换与变量使用及相关问题

    PostgreSQL中日期类型与字符串类型的转换方法 示例如下: postgres=# select current_date; date ------------ 2015-08-31 (1 row ...

  7. PostgreSQL 中定义自己需要的数据类型

    PostgreSQL解决某系数据库中的tinyint数据类型问题,创建自己需要的数据类型如下: CREATE DOMAIN tinyint AS smallint CONSTRAINT tinyint ...

  8. 在PostgreSQL中使用oracle_fdw访问Oracle

    本文讲述如何在PostgreSQL中使用oracle_fdw访问Oracle上的数据. 1. 安装oracle_fdw 可以参照:oracle_fdw in github 编译安装oracle_fdw ...

  9. [原创]PostgreSQL中十进制、二进制、十六进制之间的相互转换

    在PostgreSQL中,二进制.十进制.十六进制之间的转换是非常方便的,如下: 十进制转十六进制和二进制 mydb=# SELECT to_hex(10); to_hex -------- a (1 ...

随机推荐

  1. php服务端搜索,功能改进

    php中 ,一直以来,服务端搜索,我都是写一堆条件判断,搜索条件少时还好,条件一多,就显的代码有点丑陋了: 看着非常不舒服.今天在园子里看到一篇文章(http://www.cnblogs.com/xq ...

  2. Spring Cloud Gateway转发Spring WebSocket

    Spring Cloud Gateway转发Spring WebSocket 源码:https://github.com/naah69/SpringCloud-Gateway-WebSocket-De ...

  3. Navicat连接mysql报错1862

    昨天重新设置了mysql的密码 因为之前一直都是不用密码登录的 因为是公司数据库还是要密码 但是加了密码我今天打开 然后再控制台重新设置一下密码就好了 mysql -u root -p SET PAS ...

  4. 英语AmbraGrisea龙涎香

    龙涎香AmbraGrisea是抹香鲸科动物抹香鲸的肠内分泌物的干燥品.取自宰杀的抹香鲸肠内分泌物(即鲸鱼的粪便,它是抹香鲸吞食墨鱼后,胃肠道分泌出来的灰黑色的蜡状排泄物).其味甘.气腥.性涩,具有行气 ...

  5. 使用 Python 生成二维码

    在“一带一路”国际合作高峰论坛举行期间, 20 国青年投票选出中国的“新四大发明”:高铁.扫码支付.共享单车和网购.其中扫码支付指手机通过扫描二维码跳转到支付页面,再进行付款.这种新的支付方式,造就二 ...

  6. Go发送Email

    使用Go发送邮件,目前官网GO 1.12的版本的文档中,包 "net/smtp" 仅支持支持两种SMTP的认证方式.CRAM-MD5和PLAIN 认证方式. CRAM-MD5 是基 ...

  7. Django框架(七)-- 模板层:模板导入、模板继承、静态文件

    一.模板导入 要复用一个组件,可以将该组件写在一个文件中,在使用的时候导入即可 在模板中使用 1.语法 {% include '模板名字' %} 2.使用 ad.html页面 <div clas ...

  8. Python在Linux环境中安装Thrift

    1.文件下载:thrift-0.11.0.tar.gz 个人网盘下载:链接:https://pan.baidu.com/s/1MXgx8LuN4wk7ssVUD9Wzaw  提取码:xw85  2. ...

  9. Spring的感知能力 Aware

    在 Spring 框架中有一个 org.springframework.beans.factory.Aware 接口, Aware 是感知感应的意思,那么此接口的作用就是为 Spring 中的 bea ...

  10. UE4 Keynote 1

    [UE4 Keynote 1] 1.U3D中的Project,在UE4中叫 ContentBrowser,中文名叫“内容浏览器” 最多可以打开4个ContentBrowser,通过 “窗口” -> ...