假设有两个事务:T1 和 T2。
BEGIN; -- Т1
UPDATE table
SET amount = 1
WHERE id = 1;
SELECT xmin, xmax FROM table
WHERE id = 1;
-- получаем: xmin = xid транзакции Т1, xmax = 0
让我们开始第二笔交易:
BEGIN; -- T2
UPDATE table
SET amount = 2
WHERE id = 1;
-- ожидание завершения транзакции Т1
我们完成第一笔交易:
COMMIT;
我们继续第二个:
SELECT xmin, xmax FROM table
WHERE id = 1;
-- получаем: xmin и xmax равный идентификатору (xid) транзакции Т2.
问题:为什么事务 T1 在更新后开始看到 xmax = 0,而事务 T2 在更新后开始看到 xmax = xid(T2)?我想强调的是,这些值相对于更新数据的事务是可见的。
PS 我之前不知何故没有注意到这一点,并且总是认为如果事务更改了一行,那么相对于其自身,它会在新行中看到 xmax = 0,因为这是一个新元组,而且还没有人更改它。
xmin
和xmax
很好地解释了 MVCC 是如何实现的,但在实际代码中一切都更加复杂。Pageinspect将有助于澄清在这种情况下发生的情况,借助它我们将研究信息掩码:在这里,新插入的行将具有执行插入的事务的 xmin,但 xmax 不会。
现在该行的第三个版本出现了 (xmin=xmax=866),从名称为 的标志中可以明显看出为什么这样的 xmax
HEAP_XMAX_LOCK_ONLY
。通过这种方式,我们留下信息,以便下一个想要更新该行的事务必须检查是否仍然有一个事务正在运行,其 XID 等于 xmax 中写入的值。在行锁定的实现中,xmax 与其他信息掩码标志积极结合使用。