PostgreSQL 在执行 `UPDATE` 时获取的锁的确切类型是什么?

What's the exact type of lock PostgreSQL acquires when performing an `UPDATE`?

我知道程序员可以选择在执行数据库操作时获取 explicit locks,但我想更清楚地了解 Postgres 在执行常见操作时(自动)获取什么类型的锁,例如UPDATE.

好吧,让我们看看吧。

首先,打开两个连接。在第一个中(用适合您的数据库的值填写 table 等):

=# BEGIN;
=# UPDATE table SET field = x WHERE id = y;

现在,切换到另一个连接。使用 pg_stat_activity 找到另一个连接的 pid

=# SELECT pid FROM pg_stat_activity WHERE query = 'UPDATE table SET field = x WHERE id = y;';

 pid
------
 1684
(1 row)

显然,pid(进程 ID)会有所不同。

好的,现在使用 pid 找出正在使用的锁:

=# SELECT * FROM pg_locks WHERE pid = 1684;
   locktype    | database | relation |  page  | tuple  | virtualxid | transactionid | classid | objid  | objsubid | virtualtransaction | pid |       mode       | granted | fastpath 
---------------+----------+----------+--------+--------+------------+---------------+---------+--------+----------+--------------------+-----+------------------+---------+----------
 relation      |    16384 |    16385 | [null] | [null] | [null]     |        [null] |  [null] | [null] |   [null] | 4/10730            | 743 | RowExclusiveLock | t       | t
 virtualxid    |   [null] |   [null] | [null] | [null] | 4/10730    |        [null] |  [null] | [null] |   [null] | 4/10730            | 743 | ExclusiveLock    | t       | t
 transactionid |   [null] |   [null] | [null] | [null] | [null]     |          1440 |  [null] | [null] |   [null] | 4/10730            | 743 | ExclusiveLock    | t       | f
(3 rows)

现在,ExclusiveLock都在交易和虚拟交易上。我们可以忽略它们——几乎每笔交易都会出现它们,无论它在做什么。

但是 RowExclusiveLock 有一个数据库和关联关系。关系是您正在更新的table。

所以您问题的正确答案是 RowExclusiveLock

现在您可以 ROLLBACKCOMMIT 更新交易并清理。如果你想知道你SELECT FOR UPDATE时使用的锁类型,你可以按照相同的步骤。

请注意,这是最简单的情况:更新一行一行 table。更复杂的更新可能有更多与之关联的锁。