由于某些业务原因,我正在运行查询SELECT * FROM table WHERE updated_at > $1 AND user_id = $2;
。
考虑两个事务 A 和 B,它们正在更新表中的行:UPDATE table SET value = $1, updated_at = NOW() WHERE id = $2;
。事务 A 首先开始,因此updated_at
A 的 row 早于 B 的 row updated_at
。然而,由于某种原因,A 放慢了速度,B 先提交了。
如果第一个查询在 A 提交之前运行,则软件将显示 B 的行,但不会显示 A 的行,企业表示这是不可接受的。
这可以通过使用来解决pg_xact_commit_timestamp()
,但是当事务完成而不是提交时返回(这可能适合我的用例)。
另一个解决方案可能是在更新行之前运行事务SELECT FROM table WHERE user_id = $1 FOR UPDATE;
,但这些查询是更大事务的一部分,我认为这会破坏写入性能。
一个简单的解决方案似乎是让事务 B 等待 A 提交。有办法做到这一点吗?
如果您有更大的事务,则使用
now()
或current_timestamp
是有问题的,因为这些函数返回在数据库事务开始时获取的事务时间戳。clock_timestamp()
,它返回当前时间,会更好。尽管如此,首先提交的事务可能会以较晚的时间戳结束。我同意锁是一个糟糕的解决方案:它们不利于性能,甚至可能导致死锁。
我质疑这个要求。为什么数据库事务提交的时间很重要?
我猜想“业务”并不真正关心事务何时提交,他们想要可靠的事务排序。PostgreSQL 中的事务没有明确定义的顺序。您所需要的只是一个逻辑顺序。我想说,如果您显示的语句是事务中的最后一条语句,并且您使用
clock_timestamp()
,那么解决方案很好。您的时间戳定义了事务的顺序。实际提交时间(不久之后)是无关紧要的。