クラスターマスターを指定するSQLステートメント
-
11-07-2019 - |
質問
ノードの1つをマスターとして指定する必要があるクラスター化されたアプリケーションがあります。クラスターノードは、 nodeID 、 isMaster 、 lastTimestamp の列を持つテーブルで追跡されます。
クラスター内の各ノードは、 X 秒ごとにマスターになろうとします。ノードは、次のいずれかの場合にのみマスターになることができます
- 他のマスターノードはありません
- 現在のマスターノードの lastTimestamp は 2 * X だけ古い
上記の条件のいずれかが満たされた場合
- 現在のマスターノードの isMaster をクリアする必要があります
- 新しいマスターノードの isMaster を設定する必要があります
- 新しいマスターノードの lastTimestamp は、「今」のタイムスタンプに設定する必要があります。
2つ以上のノードがマスターになることなく上記を達成するための単一(ポータブル)SQLステートメントとは何ですか?
解決
この種の調整は、通常、DBMSで実行されるアプリケーションではなく、DBMS自体によって処理されますか?私もおなじみのDBMSでそれを行う方法を構想することができますが、システムについて詳しくは知りません(おそらく共有ディスクを使用しているため、すべてのノードが同じデータを参照します。おそらく、同時アクセスを防止するロックプロトコルがあります。データに対して;定期的にlastTimestampを更新するのはマスターノード上のユーザープロセスですか)、多くのことを支援するのは難しいでしょう。また、Jamie Loveが指摘したように、DBMSでは、複数のプロセスが関連レコードへのアクセスを調整できるようにする必要があります。メインの関連レコードは現在のマスターレコードです。
[編集済み:読みすぎていたのかもしれません。
単一のUPDATEステートメントは、テーブルの2つの行で差分更新を行う必要があり、2つの更新のうち1つのみが可能な場合は失敗する必要があります。つまり、現在のマスターを非マスターに変更すると同時に、マスターになるように独自のレコードを変更する必要があります。 1つの問題は、DBMSが「1行のみがマスターになる」制約をどのように強制するかです。それが機能し、問題がある場合はステートメント全体が失敗すると想定しましょう-あるべきです。列名を提供する場合でも、なぜ人々はテーブル名を頻繁に省略するのですか?まあ、テーブル名は以下 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」フラグを持つ行が1つだけであることを保証するための(おそらく神話上の)制約があるため、マスターが最新の場合、これは必要に応じて失敗します。
テストされていないSQL!
]
他のヒント
Oracleデータベースのソリューションは想像できますが、移植性があるかどうかはわかりません。なぜこれは単一の移植可能なSQLステートメントである必要があるのですか?ほとんどのデータベースでは、テーブルのロックとトランザクションが許可されています。これにより、このようなことを複数のステートメントで実行できます。