PostgreSQL - 行锁定是否取决于事务中的更新语法?

PostgreSQL - Does row locking depends on update syntax in transaction?

我有一个名为 user_table 的 table,它有 2 列:id(整数)和 data_value(整数)。

这里有两笔交易结果相同:

-- TRANSACTION 1

BEGIN;

UPDATE user_table 
SET data_value = 100
WHERE id = 0;

UPDATE user_table 
SET data_value = 200
WHERE id = 1;

COMMIT;

-- TRANSACTION 2

BEGIN;

UPDATE user_table AS user_with_old_value SET
    data_value = user_with_new_value.data_value
FROM (VALUES
    (0, 100),
    (1, 200)  
) AS user_with_new_value(id, data_value) 
WHERE user_with_new_value.id = user_with_old_value.id;

COMMIT;

我想知道应用在行上的锁是否有区别。

如果我没理解错的话,事务 1 会先锁定用户 0,然后锁定用户 1,然后释放两个锁。

但是事务 2 是做什么的? 它做同样的事情还是做:锁定用户 0 和用户 1,然后释放两个锁?

这是有区别的,因为如果我有两个并发事务,如果我将查询写为第一个事务,我可能会遇到死锁问题。但是如果我像第二个那样写我的交易,我会 运行 陷入死锁问题吗?

如果它做同样的事情,有没有办法写这个事务,以便在事务开始时,在做任何事情之前,事务检查它需要更新的每一行,等到所有这些行都被更新未锁定,然后同时锁定所有行?

链接: 第二笔交易的语法来自:Update multiple rows in same query using PostgreSQL

两个事务锁定相同的两行,并且都可以运行进入死锁。不同的是,第一个事务总是按一定顺序锁定两行。

如果您的 objective 是为了避免死锁,第一个事务更好:如果您制定规则,任何事务必须首先用较低的 id 更新用户,那么这样的两个事务就不能彼此死锁(但它们仍然可以与不遵守该规则的其他交易发生死锁)。