PostgreSQL: Transakce v PL/pgsql - Řešení problému s připojením

25. 11. 2017 5:42 (aktualizováno) Michal Šalko

Nepředstavitelné se stalo realitou: Dblink fungoval spolehlivě, než … Když jsem spustil svoji napsanou funkci, která rozsekávala funkčnost na několik transakcí přes dlblink, tak funkce vrátila tuto hlášku :

ERROR:  could not establish connection
DETAIL:  could not connect to server: Cannot assign requested address
    Is the server running on host "192.643.1.434" and accepting
    TCP/IP connections on port 5432?

CONTEXT:  SQL statement "SELECT dblink_exec('fdw_local',lsql)"
PL/pgSQL function s13.f_vypocet_s_ins(integer,integer) line 183 at SQL statement 

Byl to problém, který jsem musel řešit. Nebylo představitelné, aby se nedokončila funkce v případě, že by došlo k výpadku spojení.

K řešení se nabízela vlastnost funkcí vracet jinou hodnotu  v případě, že skončí v pořádku nebo špatně. Obecný vzor je tento :

CREATE OR REPLACE FUNCTION funkce()
  RETURNS boolean AS
$BODY$
DECLARE

BEGIN
  -- vlastni funkcnost

  -- Prikaz probehne funkce vrati true
   RETURN true;
EXCEPTION
WHEN OTHERS THEN

     -- Prikaz neprobehne funkce vrati false
     RETURN false;
END;
$BODY$
LANGUAGE plpgsql; 

Vytvořil jsem proto funkci, která provede přes dblink dotaz a v případě, že ztroskotá, spojení nikoliv vzdálená funkce tak vrátí false.

CREATE OR REPLACE FUNCTION dblink_comand(lsql text)
  RETURNS boolean AS
$BODY$
DECLARE
  lerr boolean;
BEGIN
   SELECT ret INTO lerr
      FROM  dblink('fdw_cdc',lsql) as t(lerr boolean);
   RETURN true;
EXCEPTION
WHEN OTHERS THEN
     RETURN false;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100; 

Mnozí by šli ještě dále a vraceli by tři stavy :

  • 1 – pošlo
  • 0 – chyba spojení
  • –1 – chyba na vzdáleném sql dotazu

V spouštěcí funkci jsem vše dal do nekonečné smyčky, která v případě pádu spojení se o něj pokoušela i nadále.

lvys boolean;

        -- Protoze muze dojit k vypadku spojeni, tak se vola dblink do te doby, nez se provede
        LOOP
           SELECT dblink_comand INTO lvys FROM  dblink_comand(lsql);
           EXIT WHEN lvys;
        END LOOP; 

Opět. Mnozí z nás by namítali, že je fajn, když funkce raději se neprovede a ne blokovat zdroje v nekonečné smyčce. 

Sdílet