PostgreSQL 锁定模式

Posted

技术标签:

【中文标题】PostgreSQL 锁定模式【英文标题】:PostgreSQL locking mode 【发布时间】:2013-04-09 05:22:02 【问题描述】:

来自这个文档http://www.postgresql.org/docs/current/static/explicit-locking.html

我知道 PostgreSQL 提供了多种锁模式来控制对表中数据的并发访问。

我的问题是我有很多会话将访问我的数据库,但我很困惑我应该创建 1 个 40 列的大表还是许多列更少的表(一对一关系)。

    因为当我选择数据时,我会选择所有数据 ---> 当我使用 INNER JOIN 从许多表中选择时需要更多时间,但从 1 个大表中选择所需时间更短。所以如果我使用很多表,我的 php 响应会变慢。

    但是当我只使用一张表同时许多会话会更新我的表中的数据时,我害怕死锁或延迟,因为命令 UPDATE、DELETE 和 INSERT 在目标表上获取 ROW EXCLUSIVE 锁定模式。一般情况下,任何修改表中数据的命令都会获得这种锁定模式。

谁能建议我应该采用哪种最佳方法?一张大桌还是多桌?

【问题讨论】:

如果不知道您在其中存储了什么,就无法回答您对一张大桌子或多张桌子的问题。标准建议是规范化您的架构bkent.net/Doc/simple5.htm 我存储了设备信息,例如 id、name、public ip、private ip、gateway、mask、external port、internal port 等。我很困惑我应该把很多东西做成一张大表列或将其拆分为多个表,用于 exp:dev_info、dev_ip、dev_port 要解决您的“慢查询”,请阅读此wiki.postgresql.org/wiki/SlowQueryQuestions 并相应更新您的问题。 【参考方案1】:

INSERTUPDATEDELETE 确实必须在要更新的表上获得ROW EXCLUSIVE 锁定。

但是,这个锁并不妨碍SELECT 正常工作。 SELECT 只需要 ACCESS SHARE 锁。这个锁兼容ROW EXCLUSIVE——也就是说,你可以完美地执行SELECT,而其他数据由INSERTUPDATEDELETE更新,只要你不获取任何显式锁。

换句话说,使用第二种方法时,您永远不会看到任何死锁(只是不要使用SELECT FOR UPDATE,您会没事的)。

在PostgreSQL documentation阅读更多内容。

【讨论】:

如果第一种方法 UPDATE A 列,第二种方法也 UPDATE 其他 B 列,会等到第一个 UPDATE 事务完成再更新第二个,还是会发生冲突? 您应该阅读more about MVCC。 TLDR:如果完全相同的行被更新,第二个更新可能等待第一个。在这种情况下,标准化应该会有所帮助。 所以要更新表上的 ROW 排他锁,但只锁定我要更新的行,对吗?不是整张桌子?第一次更新:更新 mytable SET ... WHERE key = 1; 这是正确的 - UPDATE 只有在尝试更新与另一个仍在更新的唯一密钥完全相同的唯一密钥时才会锁定。否则,它们将运行而不会减速。 所以锁定表只是为了防止其他事务想要删除我想要更新的列。这意味着 ROW EXCLUSIVE 可以被多个事务持有,对吧?

以上是关于PostgreSQL 锁定模式的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQl 正确锁定新实体的创建

PostgreSQL 锁定行无限期

PostgreSQL 服务器启动失败,无法创建锁定文件:权限被拒绝

Postgresql 选择直到达到一定的总量并锁定

如何在 postgresql 中进行一些未经授权的登录尝试后锁定数据库用户帐户

为啥 INSERT 查询无限期挂起并锁定 PostgreSQL 数据库和 pgAdmin