PG统计信息不正确的一个案例

0    50    2

Tags:

👉 本文共约1476个字,系统预计阅读时间或需6分钟。

统计信息不对

在手工进行分析之后,为什么这些数据还是 0 呢

图片

原来这个表是基于 TimescaleDB 的一个超表,分区在 TimescaleDB 中被称之为 chunk ,TimescaleDB 会自动调整 chunk 的大小,且按时间、空间自动分片。

图片

因此这个问题现象和分区表是类似的,看个栗子 👇🏻

可以看到父表的数据是空的,数据体现在子表上。当然这是最常见的一种情况,还有一种情况,这里先卖个关子,继续往下看。

本人提供Oracle、MySQL、PG等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!

我们知道在 PostgreSQL 中,统计信息的收集是当表上行数的增删改到达了阈值 (autovacuum_analyze_scale_factor + autovacuum_analyze_threshold) 之后由后台进程 autovacuum 来收集的,而统计信息又是由 analyze 来更新的,这貌似就陷入到了鸡生蛋还是蛋生鸡这样一个孰先孰后的问题。对于这种问题,其实一般数据库内都会有一个所谓的"计数器",PostgreSQL 也不例外,这个计数器正是 pg_stat_all_tables,看下视图定义 👇🏻

一目了然,关于表上各个维度的计数器,而这个统计的过程则是由 stats collector 进程来做的。而其他的比如 pg_stat_user_tables / pg_stat_sys_tables 则是基于 pg_stat_all_tables 的视图。因此,数据库在运行过程中,stats collector 会实时收集数据库内的活动状态,那么这里就引申到 stats collector 进程了

在代码中,stats collector 进程初始化的步骤中有一步会去绑定 UDP 端口,检查一下

确实如此。那么让我们故意使个坏,提供一个错误的地址映射给数据库

重启数据库之后,这次就没有 stats collector 进程了。在日志中也有所体现

当然这个是最容易想到的一个方式,stats collector 进程没了,当然就没有统计信息可言了,数据库陷入到了一个危险的境地,autovacuum 也会罢工,这种方式很直观,巡检一下就可以正常检测出来。

别急,让我们再看一个骚一点隐晦一点的

注意差异,这次变成了 ipv6

小小操作一下,让本地环回地址禁止所有的 ipv6

这样我们就关闭掉了环回地址的 ipv6 ,但是此时数据库还在兢兢业业地在收集统计信息中,奈何ipv6此时已经没有响应。无奈数据库只能沿用陈旧的统计信息将就将就

因此在这段期间做的任何操作都不会有统计信息(新的对象没有统计信息,旧的对象则使用最近一次的统计信息)

恢复之后,可以看到 test 这个新建对象的统计信息全是空的 👇🏻

至于为什么前面会夯住,不难理解,查询需要借助 stats collector 后台进程去查询统计信息,而 stats collector 已经没有响应了,用 strace 跟踪一下👇🏻

小结

PostgreSQL 使用标准 POSIX 函数 getaddrinfo(3) 来解析本地主机,然后遍历该调用返回的所有地址,创建 UDP 套接字并进行连通性测试,直到有一个可用的套接字。因此假如在进行一些诸如主机迁移、数据库迁移之类的事情,不要忘记这个可能的危害!否则表膨胀/年龄炸弹/长事务等危害会接踵而至。

参考

https://mp.weixin.qq.com/s/uiH95aJF5lAcb4jcC3TI5w

标签:

头像

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

1 × 2 =

 

嘿,我是小麦,需要帮助随时找我哦
  • 18509239930
  • 个人微信

  • 麦老师QQ聊天
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部
返回顶部