【发布时间】:2026-01-25 17:40:01
【问题描述】:
据我了解,postgres 使用两个额外的字段 Xmin 和 Xmax 来实现 mvcc, 假设我们有 Employee 表,其中包含 id 和 name 列。
以下是一些 crud 操作以及它们如何同时工作(考虑隔离级别 = READ_COMMITTED),问题是何时何地获取实际锁。
- 插入 -> 新事务插入一条新记录,在提交之前对其他事务不可见,因此在这种情况下没有问题,也不需要锁定或版本控制。假设 id = 1,name = "aa" 被插入。 Postgres 为 mvcc Xmin = current txn id(假设为 100)和 Xmax = 0/null 添加了 2 个额外的列。
id | name | Xmin | Xmax
------------------------------
1 | aa | 100 | null
-
使用并发读取更新 -
一)。一个新事务开始将名称更新为“bb”(对于 id = 1)。同时还有一个 事务开始读取相同的数据。
b)。使用 Xmin = 当前事务 id(假设为 200)和 Xmax = null 以及 id = 1、name = bb 创建一个新的元组(postgres 中的不可变对象表示一行)。旧版本的 id = 1 也被更新为 Xmax = 200。读取事务看到旧版本的数据 Xmin = 100 并返回。 在这种情况下是否需要任何锁定?我认为没有,但它可能会更新旧元组的 Xmax。
以下是多个版本的相同记录(仅用于说明目的),最新版本的 Xmax = null。
id | name | Xmin | Xmax
------------------------------
1 | aa | 100 | 200
1 | bb | 200 | null
-
同时更新更新 -
一)。交易(txn id = 300)开始将 id = 1 更新为 name = cc。另一个事务(txn id = 400)开始将同一记录(id = 1)更新为name = dd。如果这种情况也通过创建新元组并标记旧元组的 Xmax 以同样的方式进行,那么我认为它会产生问题,因为 300 和 400 都会创建一个新元组并标记旧元组的 Xmax = txn id。在这种情况下,更新可能会丢失。
在这种情况下,排他锁是由第一个 txn 获取,其他并发更新 txns 会等到任何正在进行的 txn 完成或 postgres 有其他处理方式吗?
【问题讨论】:
标签: database postgresql database-design database-concurrency mvcc