Разве такого рода координация обычно не выполняется самой СУБД, а не приложениями, работающими на СУБД? Я также могу предусмотреть способы сделать это в СУБД, с которой я знаком, но не зная больше о вашей системе (она, вероятно, использует общие диски, поэтому все узлы видят одни и те же данные; есть предположительно протоколы блокировки, которые предотвращают одновременный доступ) к данным, является ли это пользовательский процесс на главном узле, который периодически обновляет lastTimestamp), будет трудно помочь многим. И, как отметил Джейми Лав, СУБД должна позволять нескольким процессам координировать доступ к соответствующим записям - основной релевантной записью является текущая основная запись.
[ Отредактировано : Может быть, я слишком много читал об этом.
Один оператор UPDATE должен выполнять дифференциальные обновления в двух строках таблицы и должен завершиться ошибкой, если возможно только одно из двух обновлений. То есть он должен изменить текущий мастер, чтобы он не был мастером, а также изменить свою собственную запись, чтобы он стал мастером. Одна проблема заключается в том, как СУБД обеспечивает ограничение «только одна строка может быть главной». Давайте предположим, что это работает, и утверждение в целом потерпит неудачу, если возникнет проблема - как и должно быть. Почему люди так часто опускают имя таблицы, даже если они предоставляют имена столбцов? Ну что ж, имя таблицы здесь и далее 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):
- поле lastTimestamp для нового мастера установлено на текущую метку времени, но старый мастер не изменяется.
- поле isMaster заменено на 'Y' для нового мастера и на 'N' для старого мастера.
Теория, лежащая в основе предложения WHERE:
- Изменять запись для текущего узла можно только в том случае, если это не текущий мастер или запись для текущего главного узла, если этот узел не является текущим узлом, а отметка времени превышает 120 секунд («2 * X» в вопрос) старый.
Поскольку существует (возможно, мифическое) ограничение, гарантирующее, что только у одной строки есть флаг 'Y', это должно произойти сбой при необходимости, когда мастер обновлен.
Непроверенный SQL!
]