一个PG主键重复的案例

0    786    2

Tags:

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

前言

昨天早上同事转了一封邮件过来,发现某张表的主键重复了!😵 印象中这是第二次遇到了,让我们一起分析下这个罕见的案例。根因很重要呀!耐心看完

分析

出问题的表结构不复杂,主要字段如下(部分信息做了脱敏)

昨天开发反馈更新的时候提示主键重复,于是上去看了一下

果然主键重复了,DBA 表示惊呆了!主键的功能就是非空 + 唯一,那是哪里出了问题呢?

先看下这两条数据的事务状态,是否是可见性导致的

第一条数据 xmax 字段有值,说明这条数据要么被更新过,要么获取过行锁,这点很好验证

再看看 ctid

根据过往的一些经验,初步怀疑可能是索引出了问题,比如 index only scan 仅在索引中取数据,索引和存储上的数据不一致,这个是有具体的案例的,可以翻下之前的文章。看下执行计划:

顺序扫描和索引扫描返回的数据一致,那不是索引的问题。不过为了确保索引是正确的状态(属实踩雷踩多了),还是使用插件 amcheck 检查了一下。

em,索引也是正确的状态,说明有别于以往的案例。继续分析一下

CTID 表示这两行数据分别位于 9789 和 9790 这两个数据块,使用 pageinspect 窥探一下底层文件

这里可以看到一些差别,第一行数据的 ctid 指向了 '(106234,2)',同时表示该行已经冻结过了 XMIN_INVALID|XMIN_COMMITTED

通过 pageinspect 查看,发现有这行数据,但是通过指定查询是没有数据的

假如查询的时候第一条数据通过 ctid '(9789,8)' 到 ctid '(106234,2)' 这个 ctid 链进行查找的话,数据的确无法可见,也就不会有第一条数据了,主键也就不会重复了。难道是数据不一致了?ctid 链出问题了?内存中的数据和底层的数据不一致?

后面仔细一想,发现是我想多了,这个其实是正常的机制,也是我最开始被绕进去的地方 👇🏻 做个小实验:

相信各位也看明白了,第一行数据依旧在哪里,但是通过 pageinspect 看的话,ctid 均是指向的第二行数据,即使第二行数据已经回滚了,通过 MVCC 和行上的 infomask(XMIN_INVALID) 来确保第二条数据不可见。所以,这个是正常的现象。这个不起眼的地方属实把我绕进去了,各种计算偏移量去看底层文件。

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!
一个PG主键重复的案例后续精彩内容已被小麦苗无情隐藏,请输入验证码解锁本站所有文章
验证码:
请关注本站微信公众号,回复“小麦苗博客”,获取验证码。在微信里搜索“DB宝”或者“www_xmmup_com”或者微信扫描右侧二维码都可以关注本站微信公众号。

标签:

Avatar photo

小麦苗

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

您可能还喜欢...

发表回复

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

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

  • 回到顶部