插入和选择时postgresql如何锁定表?

ssb*_*ssb 4 postgresql concurrency locking

我正在将数据从一个表迁移到另一个表,在这种环境中,任何长锁或停机时间都是不可接受的,总共大约 80000 行。本质上,查询归结为这个简单的案例:

INSERT INTO table_2
SELECT * FROM table_1
JOIN table_3 on table_1.id = table_3.id
Run Code Online (Sandbox Code Playgroud)

正在读取所有 3 个表,并且可以随时插入。我只想运行上面的查询,但我不确定锁定是如何工作的,以及在操作过程中表是否完全无法访问。我的理解告诉我,只有受影响的行(新插入的)会被锁定。表 1 刚刚被选中,所以没有危害,并发插入是安全的,所以表 2 应该可以自由访问。

这种理解是否正确,我可以在生产环境中毫无顾虑地运行此查询吗?如果它不安全,那么实现此目的的标准方法是什么?

Nic*_*nes 9

你没事。

如果你对细节感兴趣,你可以阅读多版本并发控制,或者Postgres MVCC 实现的细节,或者它的各种锁定模式如何交互,但是文档中很好地总结了对你的情况的影响:

阅读从不阻碍写作,写作从不阻碍阅读

简而言之,存储在数据库中的每条记录都附有一些版本号,并且每个查询都知道要考虑哪些版本以及忽略哪些版本。

这意味着INSERT可以安全地写入表而不锁定它,因为任何并发查询将简单地忽略新行,直到插入事务决定提交。

  • @ssb:不,他们不会。由于 MVCC 可见性规则对其他会话隐藏了“INSERT”的影响,因此它不需要锁定任何人,因此永远不会陷入等待获取锁的状态。当它为新行保留物理存储位置时,可能有一个非常简短的关键部分,但在语句持续时间内没有保留任何内容。(一个例外是,如果两个插入尝试将相同的值放入“UNIQUE”列中;在这种情况下,第二个语句将阻塞,直到第一个语句提交或回滚。) (3认同)