我有群集应用程序,需要将其中一个节点指定为主节点。群集节点在 nodeID , isMaster , lastTimestamp 列的表格中进行跟踪。
群集中的每个节点都会尝试每 X 秒成为主节点。如果
,节点只能成为主节点当满足上述条件之一时
什么是单个(可移植)SQL语句来实现上述目标而不会有两个或更多节点成为主节点?
答案 0 :(得分:1)
我可以想象一个Oracle数据库的解决方案,但我不确定它是否可移植。为什么这需要是一个可移植的SQL语句?大多数数据库允许表锁定和事务,它允许您在多个语句中执行此类操作。
答案 1 :(得分:1)
这种协调通常不是由DBMS本身处理,而是由DBMS上运行的应用程序处理吗?我也可以设想在我熟悉的DBMS中实现它的方法,但是在不了解您的系统的情况下(可能是使用共享磁盘,因此所有节点都看到相同的数据;可能有锁定协议阻止并发访问)对于数据;是主节点上的用户进程是否定期更新lastTimestamp),这将很难提供帮助。而且,正如Jamie Love指出的那样,DBMS应该允许多个进程协调对相关记录的访问 - 主要相关记录是当前的主记录。
[已编辑:也许我读得太多了。
单个UPDATE语句必须对表的两行执行差异更新,如果只有两个更新中的一个可能,则必须失败。也就是说,它必须将当前主服务器更改为非主服务器,并且还要更改其自己的记录,以便它是主服务器。一个问题是DBMS如何强制执行“只有一行可能是主”约束。让我们假设如果存在问题,那么作品和整个陈述将会失败 - 正如它应该的那样。为什么人们经常省略表名,即使他们提供列名?哦,表名在下文中是 ClusterControl 。每个节点必须以某种方式知道自己的NodeID;我使用{MyNodeID}来指示SQL中出现的位置。
您需要单独的心跳更新:
UPDATE ClusterControl
SET lastTimestamp = CURRENT_TIMESTAMP
WHERE NodeID = {MyNodeID};
“抓住主要状态”更新可能是:
UPDATE ClusterControl
SET lastTimestamp = (CASE
WHEN NodeID = {MyNodeID} THEN CURRENT_TIMESTAMP
ELSE lastTimestamp END),
isMaster = (CASE
WHEN NodeID = {MyNodeId} THEN 'Y'
ELSE 'N' END)
WHERE (NodeID = {MyNodeID} AND isMaster = 'N') OR
(NodeID != {MyNodeID} AND
lastTimestamp < CURRENT_TIMESTAMP - INTERVAL '120' SECOND AND
isMaster = 'Y'
);
'抓住主要状态'更新背后的理论是(SET子句):
WHERE子句背后的理论是:
由于存在一个(可能是神话般的)约束来确保只有一行具有'Y'标志,因此当主服务器是最新的时,这应该根据需要失败。
未经测试的SQL!