関数特性
言語: PLPGSQL
戻り値: integer
failed_node to backup_node からフェイルオーバを開始します。この関数は全てのノードで呼ばれなければならず、そして全てのノードのデーモンの再起動に待機しなければなりません。declare p_failed_node alias for $1; p_backup_node alias for $2; v_row record; v_row2 record; v_n int4; begin -- ---- -- 中枢構成にロックの取得 -- ---- lock table sl_config_lock; -- ---- -- 全ての一貫性の検査が第一 -- 故障ノードへの経路を全てのシステムが所有しているかの検査 -- 同時にバックアップノードへの経路があるかも検査 -- ---- for v_row in select P.pa_client from sl_path P where P.pa_server = p_failed_node and P.pa_client <> p_backup_node and not exists (select true from sl_path PP where PP.pa_server = p_backup_node and PP.pa_client = P.pa_client) loop raise exception 'Slony-I: cannot failover - node % has no path to the backup node', v_row.pa_client; end loop; -- ---- -- Check all sets originating on the failed node -- ---- for v_row in select set_id from sl_set where set_origin = p_failed_node loop -- ---- -- 故障ノードのオリジンである全てのセットで -- バックアップノードが購読されているかの検査 -- ---- select into v_row2 sub_forward, sub_active from sl_subscribe where sub_set = v_row.set_id and sub_receiver = p_backup_node; if not found then raise exception 'Slony-I: cannot failover - node % is not subscribed to set %', p_backup_node, v_row.set_id; end if; -- ---- -- 購読動作が有効かの検査 -- ---- if not v_row2.sub_active then raise exception 'Slony-I: cannot failover - subscription for set % is not active', v_row.set_id; end if; -- ---- -- 他に購読ノードがあれば、バックアップノードは -- 発信ノードになる必要も同時にあります。 -- ---- select into v_n count(*) from sl_subscribe where sub_set = v_row.set_id and sub_receiver <> p_backup_node; if v_n > 0 and not v_row2.sub_forward then raise exception 'Slony-I: cannot failover - node % is not a forwarder of set %', p_backup_node, v_row.set_id; end if; end loop; -- ---- -- 厳しく故障ノードの全ての接続を停止 -- ---- perform terminateNodeConnections( '_schemadoc_Node_' || p_failed_node); -- RebuildListenEntries() が有効になっていれば以下のコードは使われなくなる -- 事を覚えておいてください。 if false then -- ---- -- 故障ノードから何かを監視している全てのノードに -- 代わりとしてバックアップノード上のそれらを監視するようにします。 -- ---- for v_row in select * from sl_listen where li_provider = p_failed_node and li_receiver <> p_backup_node loop perform storeListen_int(v_row.li_origin, p_backup_node, v_row.li_receiver); end loop; -- ---- -- 故障ノードが監視していた全ての事象を -- バックアップノードが監視する様にします。 -- ---- for v_row in select li_origin, li_provider from sl_listen where li_receiver = p_failed_node and li_provider <> p_backup_node loop perform storeListen_int(v_row.li_origin, v_row.li_provider, p_backup_node); end loop; -- ---- -- 故障ノードから何んでも受け取る -- 全ての sl_listen エントリを削除します。 -- ---- delete from sl_listen where li_provider = p_failed_node or li_receiver = p_failed_node; end if; -- ---- -- セットの移動 -- ---- for v_row in select S.set_id, (select count(*) from sl_subscribe SUB where S.set_id = SUB.sub_set and SUB.sub_receiver <> p_backup_node and SUB.sub_provider = p_failed_node) as num_direct_receivers from sl_set S where S.set_origin = p_failed_node for update loop -- ---- -- バックアップノードが唯一の直接購読ノードか否か。 -- ---- if v_row.num_direct_receivers = 0 then raise notice 'failedNode: set % has no other direct receivers - move now', v_row.set_id; -- ---- -- バックアップノードは唯一の直接購読ノードで、セットのすぐに移動します。 -- バックアップノード上でそれ自身は、次の作業をします。 -- 全てのユーザモードのトリガーのリストア -- ログトリガーの追加、購読の削除、および -- 旧くなった setsync ステータスの削除 -- ---- if p_backup_node = getLocalNodeId('_schemadoc') then for v_row2 in select * from sl_table where tab_set = v_row.set_id loop perform alterTableRestore(v_row2.tab_id); end loop; end if; update sl_set set set_origin = p_backup_node where set_id = v_row.set_id; if p_backup_node = getLocalNodeId('_schemadoc') then delete from sl_setsync where ssy_setid = v_row.set_id; for v_row2 in select * from sl_table where tab_set = v_row.set_id loop perform alterTableForReplication(v_row2.tab_id); end loop; end if; delete from sl_subscribe where sub_set = v_row.set_id and sub_receiver = p_backup_node; else raise notice 'failedNode: set % has other direct receivers - change providers only', v_row.set_id; -- ---- -- バックアップノードは唯一の直接購読ノードではありません。 -- 意味する所は、この時点で全ての直接購読ノードをバックアップノードから -- 受け取るようにリダイレクトし、バックアップノードそれ自身は -- 他から受け取るようにします。 -- 管理ユーティリティは slon エンジンが再起動するまで待機し、 -- そのあと最高位の SYNC を所有しているノード上で failedNode2() -- を呼び出し、そしてこれを後でバックアップノード上に -- リダイレクトします。 -- ---- update sl_subscribe set sub_provider = (select min(SS.sub_receiver) from sl_subscribe SS where SS.sub_set = v_row.set_id and SS.sub_provider = p_failed_node and SS.sub_receiver <> p_backup_node and SS.sub_forward) where sub_set = v_row.set_id and sub_receiver = p_backup_node; update sl_subscribe set sub_provider = p_backup_node where sub_set = v_row.set_id and sub_provider = p_failed_node and sub_receiver <> p_backup_node; end if; end loop; -- sl_listen テーブルの書き換え perform RebuildListenEntries(); -- ---- -- ノードデーモンの再起動の確認 -- ---- notify "_schemadoc_Restart"; -- ---- -- とりあえずこれでお終い -- ---- return p_failed_node; end;