我有一个后端进程,用于维护PostgreSQL数据库中的状态,该数据库需要对前端可见。我想:
正确处理后端停止并启动。仅这一点就像在启动时清除后端状态表一样简单。
防止后端的多个实例相互踩踏。应该只有一个后端进程,但如果我不小心启动了第二个实例,我想确保第一个实例被终止,或者第二个实例被阻塞,直到第一个实例终止。
我能想到的解决方案包括:
利用我的后端进程侦听端口的事实。如果进程的第二个实例尝试启动,它将失败并显示“Address in in use”。我必须确保在连接到数据库和擦除状态表之前执行listen
步骤。
打开辅助连接并运行以下命令:
BEGIN;
LOCK TABLE initech.backend_lock IN EXCLUSIVE MODE;
注意:IN EXCLUSIVE MODE
的原因是LOCK
默认为AccessExclusive锁定模式。这与pg_dump
获取的AccessShare锁相冲突。
不要提交。将表保持锁定直到程序死亡。
维护一个在PostgreSQL数据库中维护状态的单例后端进程有什么好的模式?理想情况下,我会在连接期间获得锁定,但LOCK TABLE不能在事务之外使用。
考虑具有“代理”进程的应用程序,该进程与数据库通信,并接受来自客户端的连接。每次客户端连接时,代理进程都会向数据库添加一个条目。这有两个好处:
前端可以查询数据库以查看连接的客户端。
当另一个名为initech.objects
的表中的行发生更改,并且客户端需要了解它时,我可以创建一个触发器来生成客户端列表以通知更改,将其写入表中,然后使用NOTIFY唤醒经纪人流程。
如果没有连接客户端表,应用程序必须确定要通知的客户端。在我的情况下,这变得非常混乱:在内存中存储initech.objects
表的副本,并且每当行更改时,将旧行和新行分派给处理程序,以检查行是否已更改并执行如果有的话。要有效地做到这一点,需要针对存储在内存中的表和对行更改感兴趣的处理程序创建“索引”。我在代理程序中编写了SQL的索引和查询功能的复制品。我宁愿把这项工作转移到数据库。
总之,我希望代理进程在数据库中维护其某些状态。它极大地简化了对客户端的配置更改调度,但它要求一次只将一个代理实例连接到数据库。
答案 0 :(得分:2)
可以通过咨询锁
来完成http://www.postgresql.org/docs/9.1/interactive/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS
答案 1 :(得分:0)
我今天以一种我认为简洁的方式解决了这个问题:
CREATE TYPE mutex as ENUM ('active');
CREATE TABLE singleton (status mutex DEFAULT 'active' NOT NULL UNIQUE);
然后你的后端程序试图这样做:
insert into singleton values ('active');
如果不这样做,则退出或等待。