FOR KEY SHARE 在PostgreSQL中的实际用途是什么?

8
我不理解在哪些情况下会实际使用它。根据此处的文档,它说:

与FOR SHARE类似,但锁定更弱:SELECT FOR UPDATE被阻止,但不是SELECT FOR NO KEY UPDATE。共享键锁定阻止其他事务执行DELETE或更改关键字值的任何UPDATE,但不会阻止其他UPDATE,也不会阻止SELECT FOR NO KEY UPDATE、SELECT FOR SHARE或SELECT FOR KEY SHARE。

但是我尝试了,它允许所有可能的更新。我甚至尝试更改键。也许我没有理解文档中所指的(从这个答案中我认为它是外键,并且因为它没有像文档中说的那样被阻止,我尝试更新所有内容,一切都没有被阻止)。我通过两个psql终端模拟了两个并发事务来进行实验。 事务1:
db1=> begin;
BEGIN
db1=> SELECT * from table_base FOR key share;
 base_id | foreign_id | nonkey1 
---------+------------+---------
 112 |          2 | plaexpl
  21 |          2 | harish
 111 |          2 | harish
(3 rows)

db1=> select * from table_foreign ;
foreign_id |  value  
------------+---------
      2 | val2
     12 | val1new
     44 | newval3
(3 rows)

db1=> \d table_base 
                  Table "public.table_base"
 Column   |         Type          | Collation | Nullable | Default 
 ------------+-----------------------+-----------+----------+---------
 base_id    | integer               |           |          | 
 foreign_id | integer               |           |          | 
 nonkey1    | character varying(50) |           |          | 
 Foreign-key constraints:
  "table_base_foreign_id_fkey" FOREIGN KEY (foreign_id) REFERENCES 
 table_foreign(foreign_id) ON UPDATE CASCADE

事务 2

db1=> begin;
BEGIN
db1=> UPDATE table_base set base_id = 221 where base_id=21;
UPDATE 1
db1=> UPDATE table_base set foreign_id = 12 where nonkey1='harish';
UPDATE 2
db1=> UPDATE table_base set nonkey1='newharish' where nonkey1='harish';
UPDATE 2
db1=> end;
COMMIT
db1=> SELECT * from table_base;
 base_id | foreign_id |  nonkey1  
---------+------------+-----------
     112 |          2 | plaexpl
     111 |         12 | newharish
     221 |         12 | newharish
(3 rows)

db1=> begin;
BEGIN
db1=> UPDATE table_foreign set foreign_id = 33 where value = 'val1new';
UPDATE 1
db1=> UPDATE table_foreign set value ='newvalfor33' where foreign_id = 33;
UPDATE 1
db1=> end;
COMMIT
db1=> SELECT * from table_foreign ;
 foreign_id |    value    
------------+-------------
          2 | val2
         44 | newval3
         33 | newvalfor33
(3 rows)

在此输入图片描述

上述示例中表的更多信息 在此输入图片描述 如果允许所有更新,那么“FOR KEY SHARE”和普通的“SELECT”有什么区别(除了阻止“SELECT FOR UPDATE”)? 这有什么实际用途?


我们能看到 \d table_base 吗? - Laurenz Albe
@LaurenzAlbe在问题中添加了屏幕截图。 - Harish Kayarohanam
@a_horse_with_no_name,我添加了屏幕截图以显示psql输出的表格。 - Harish Kayarohanam
好的,我现在会将这段与编程有关的内容翻译成中文。 - Harish Kayarohanam
我有12.1版本..我添加了9.3标签,因为这显然是引入这些锁的版本。如果它令人困惑,也许我可以删除那个标签。 - Harish Kayarohanam
@a_horse_with_no_name,我现在添加了代码。 - Harish Kayarohanam
1个回答

13

FOR KEY SHARE主要用于修改具有外键约束的表时:引用行(在远程表上)将会自动获取这样一把锁,以便不能同时修改任何引用键。

您看不到效果是因为您的表不包含PRIMARY KEYUNIQUE约束。


我将base_id更改为主键,但仍然可以更改foreign_id。 - Harish Kayarohanam
2
是的,但不是主键列。 - Laurenz Albe
是的,我检查过了,它仍然保持良好…那么为什么他们说外键不能更改呢?难道不是主键吗? - Harish Kayarohanam
1
他们没有这么说。如果您在具有外键约束的表中插入或删除行,则会在远程表上获得KEY SHARE锁。该锁将防止对远程表中的键进行修改。 - Laurenz Albe
您已经撰写了一篇博客文章:https://www.cybertec-postgresql.com/en/triggers-to-enforce-constraints/ - jian
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接