postgresql - Postgres 中的 ctid 链是否在行的并发更新下 fork ?

标签 postgresql

我正在阅读 this guidethis guide更好地了解 postgres 内部是如何工作的,而且大多数事情都是有意义的。但是,我有一个关于并发更新将如何影响 ctid 的问题。链。
据我了解,ctid s 指向“下一个”(页面,指针)组合来描述给定行的修订。但是,当两个并发事务正在执行并尝试更新同一行时会发生什么?事务具有由它们的 txid 强加的排序,但这并不能保证它们尝试更改行的顺序。这些更新的可能结果是什么?
例如,如果我们有一张表 t单列 s如第二个指南和 更新,我们可能有:

=> BEGIN;
=> UPDATE t SET s = 'BAR';
=> SELECT txid_current();

 txid_current 
--------------
         3666

=> SELECT * FROM t;

 id |  s  
----+-----
  1 | BAR
(1 row)
当我们使用 heap_page查看页面内部结构的函数,它看起来像:
=> SELECT * FROM heap_page('t',0);

 ctid  | state  |   xmin   | xmax  | t_ctid 
-------+--------+----------+-------+--------
 (0,1) | normal | 3664 (c) | 3666  | (0,2)
 (0,2) | normal | 3666     | 0 (a) | (0,2)
两个更新同时发生,最终表状态如何随
  • 两次更新的序列化级别
  • 交易开始的顺序
  • 事务写入该行页面的顺序?

  • 更新:劳伦兹是正确的。关于如何执行更新的证实伪代码,来自链接指南之一的后面,是:
    (1)  FOR each row that will be updated by this UPDATE command
    (2)       WHILE true
    
                   /* The First Block */
    (3)            IF the target row is being updated THEN
    (4)               WAIT for the termination of the transaction that updated the target row
    
    (5)               IF (the status of the terminated transaction is COMMITTED)
                           AND (the isolation level of this transaction is REPEATABLE READ or SERIALIZABLE) THEN
    (6)                        ABORT this transaction  /* First-Updater-Win */
                      ELSE 
    (7)                           GOTO step (2)
                      END IF
    
                   /* The Second Block */
    (8)            ELSE IF the target row has been updated by another concurrent transaction THEN
    (9)               IF (the isolation level of this transaction is READ COMMITTED THEN
    (10)                           UPDATE the target row
                      ELSE
    (11)                           ABORT this transaction  /* First-Updater-Win */
                      END IF
    
                   /* The Third Block */
                    ELSE  /* The target row is not yet modified or has been updated by a terminated transaction. */
    (12)                  UPDATE the target row
                    END IF
               END WHILE 
          END FOR 
    
    注意第 4 行,它描述了在另一个事务中设置 xmax 的行锁定效果。

    最佳答案

    答案比你想象的要简单:行锁防止同一行的并发修改,所以问题永远不会出现,更新链不会 fork 。

    关于postgresql - Postgres 中的 ctid 链是否在行的并发更新下 fork ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67052991/

    相关文章:

    ruby-on-rails - 现有 Postgres 表与新表中的 Json 列

    mysql - 如何从查询中选择最后一个值?

    sql - 在 Postgresql 中格式化 double 值

    java - 使用 JDBC 加速 postgresql 上的 sql 插入?

    java - 用于 spring boot 应用程序的 hibernate 投影

    mysql - 排除列值上的连接记录?

    postgresql - 如何避免使用 WAL 归档的大日志文件?

    mysql - 在多用户环境中选择数据

    spring 中的 java.lang.ClassNotFoundException : org. postgresql.Driver

    mysql - MYSQL 的 Liquibase 脚本