Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

隐藏字段xmin/xmax/cmin/cmax

xmin和xmax

  • 创建insert:

    • xmin填 当前事务ID
    • xmax填 0
  • 更新update:

    • 实际分两步,相当于操作了两行
      • 第一步delete旧行
        • xmin 不变
        • xmax填 当前事务ID
      • 第二步insert新行
        • xmin填 当前事务ID
        • xmax填 0
  • 删除delete:

    • xmin 不变
    • xmax填 当前事务ID
  • 总结

    • 填充的都是 事务ID
      • 创建的时候,会填到xmin里,而xmax默认为0
      • 删除的时候,会填到xmax里,而xmin不变
  • 用途

    • 判断upsert的时候,到底是 insert 还是 update

      INSERT INTO test VALUES (1, 2, 3) 
      ON CONFLICT ( id ) 
      DO UPDATE SET a = 5,b = 6
      RETURING
      id, ( CASE WHEN xmax <> 0 
          THEN 'UPDATE' ELSE 'INSERT' END ) AS type;
      
    • 解释

      • 如果xmax为0,则代表,是纯粹的创建
      • 如果xmax不为0,则代表删除过,反映的是旧行
    • 注意:这个不能用于update,因为纯粹的更新,反映的是新行上的xmax仍为0,而不是旧行上xmax为事务号

    • 如果不用隐藏字段,就需要用下面更麻烦的方式判断

      WITH tt AS 
      (SELECT 1 AS abc FROM test WHERE id = 1) 
      INSERT INTO test
      VALUES (1, 2, 3) 
      ON CONFLICT (id) DO
      UPDATE SET a = 5, b = 6 
      RETURNING ( SELECT abc FROM tt );
      
      • 这里用到了WITHRETURNING
        • 返回Null代表查不到,是insert
        • 返回1代表查到,是update

cmin和cmax

  • 事务内的顺序号,值基本一样,貌似是同一个东西

  • 如果

    • 一个事务只执行一个insert
      • 那么,值为0
    • 一个事务执行了两个insert
      • 那么,一个是0,一个是1
      • 代表了事务内执行的顺序
    • 一个事务只执行一个update
      • 那么,值变成了1

ctid

  • 代表了 数据行 在表中的 物理位置

  • 由一对数值组成(块编号和行索引),可以快速找到数据行

  • 注意:

    • ctid 的值有可能会改变
    • 比如发生在 VACUUM FULL
    • 所以不适合作为长期的行标识,而是要用主键

tableid

  • 代表了 表 的对象id

  • 会出现在pg_class数字字典表中

    SELECT oid, relname 
    FROM pg_class 
    WHERE relname = 'test';