PostgreSQL 中的表锁
Posted
技术标签:
【中文标题】PostgreSQL 中的表锁【英文标题】:Table lock in PostgreSQL 【发布时间】:2014-08-25 12:57:13 【问题描述】:我正在开发一个应用程序,它应该从一个表中获取数据并在另一个表中记录处理结果。所有这些都在一个线程和几台计算机上。所以我需要为此使用一些同步机制。至于我需要使用多台计算机,我必须在数据库中使用一些同步机制(在我的情况下是 PostgresSQL),而不是在代码中使用锁定。我知道 postgres 在表上提供了一些锁定,但我没有找到任何文档如何设置它。
可能已经存在一些标准解决方案吗?
【问题讨论】:
您的意思是数据库的副本不止一份?每台电脑一个? 不,一个数据库适用于所有应用程序。 我认为您需要展示处理逻辑及其分布方式。但我可能错了。 【参考方案1】:是的,Postgres 在表级别提供锁定机制。您可以使用 SQL 锁定表,然后在工作完成后将其解锁。
详情请见the explicit locking chapter of the manual。
但考虑到您的情况,您可以使用一些简单的机制来实现相同的目的,例如向表中添加一列 -locking_status 布尔值。当一台机器使用它时,您可以将其设为 TRUE,然后根据您的要求进行切换。但是,如果您有超过 1 个表,那么锁定表是唯一的选择。
您还需要处理高度可扩展的多线程程序,因为有可能一个应用程序已锁定表,然后该机器可能会停机。在这种情况下,您的表将保持锁定状态,并且应用程序只会变得无响应。 (但取决于您如何处理此状态)。在这种情况下,某种过期机制可能会有所帮助,它会在特定时间后解锁表。
希望这会有所帮助。
【讨论】:
【参考方案2】:看起来您正在尝试编写任务队列或消息队列。这些真的很难做对。您希望我推荐一个现有的、经过良好测试的实现供您使用吗?
更严重的是:表级锁是用LOCK TABLE
语句完成的;见韦德的回答。在SERIALIZABLE
隔离中还有行级锁(SELECT ... FOR [KEY] UPDATE|SHARE
)和乐观谓词锁。您还可以实现乐观并发控制(参见 Wikipedia)。
但是,实际上很难创建并发任务或消息队列。您提出的大多数解决方案实际上都会被序列化,因此一次只能运行一个任务,或者无法处理中止/崩溃等任务。
见:
Can Lost Update happen in read committed isolation level in PostgreSQL? Why do we need message brokers like rabbitmq over a database like postgres? How can I send email from PostgreSQL trigger? Concurrent processes working on a PostgreSQL table When does "select for update" lock and unlock? Postgresql table with one ID column, sorted index, with duplicate primary key并研究 Celery、ZeroMQ、ActiveMQ、RabbitMQ、Octobot 等工具。请参阅 http://queues.io/
【讨论】:
是的。我的任务是尝试编写任务队列或类似的东西。 @Vartlok 然后不要!使用现有的测试实现之一。以上是关于PostgreSQL 中的表锁的主要内容,如果未能解决你的问题,请参考以下文章