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
。
现在您可以 ROLLBACK
或 COMMIT
更新交易并清理。如果你想知道你SELECT FOR UPDATE
时使用的锁类型,你可以按照相同的步骤。
请注意,这是最简单的情况:更新一行一行 table。更复杂的更新可能有更多与之关联的锁。
我知道程序员可以选择在执行数据库操作时获取 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
。
现在您可以 ROLLBACK
或 COMMIT
更新交易并清理。如果你想知道你SELECT FOR UPDATE
时使用的锁类型,你可以按照相同的步骤。
请注意,这是最简单的情况:更新一行一行 table。更复杂的更新可能有更多与之关联的锁。