Replikace - 3 odloučená pracoviště

Top  Previous  Next

Seznam témat:

popis

řešení

 

Popis

Ide o distribuované spracovanie dát troch miestne odlúčených prevádzok vo Vrábľoch a Bratislave so základnou požiadavkou zdielania dát. Pretože miesta nie sú trvale prepojené, je nevyhnutné, aby boli kompletné dáta na všetkých miestach. Je zrejmé, že pred zahájením práce musia byť všetky databázy celkom identické. V momente, ak začnú užívatelia vytvárať dáta do každej z databáz, začnú vznikať medzi databázami rozdiely. Systém v tzv. tranzakčnom logu kontroľuje všetky tieto zmeny. V pravidelných intervaloch sa môžu databázy prepojiť a tieto zmeny si vzájomne vymeniť. Po uskutočnení výmeny sú databázy opäť celkom identické.

Na databázovej úrovni je zaznamenávaná každá zmena od posledného zaregistrovaného prenosu dát (replikácie). Akonáhle je vyvolaný prenos (je spustený agend DbRemote s patričnými parametrami), sú kontrolované tzv. publikačné skripty (to je definície toho, čo sa má prenášať a kam) a na ich základe sa vytvorí "balíček" pre ostatné databázy. Tento balíček je agentom "DbRemote" umiestnený na FTP server v dopredu pripravenom adresári a opačne sú stadiaľto zobraté balíčky, ktoré sú určené pre túto databázu. Prichádzajúci balíček je dekódovaný a formou SQL príkazov sú dáta prijaté.

ASA využíva pri replikáciách informácie uložené v LOG súbore. Každý LOG súbor obsahuje sekvencie všetkých zmien vykonaných v databáze. Každej zmene je pridelené číslo, ktoré neustále narastá (log offset), takže každý LOG súbor má nejaký počiatočný a nejaký koncový offset. Tieto údaje je možné zistiť príkazom v príkazovom riadku: dblog.exe <soubor.log>. Súbor musí byť samozrejme voľný (nezamknutý).

Predpokladá sa existencia jednej centrálnej (konsolidované) DB, ktorá je v AGF Vráble a niekoľkých vzdialených (remote) DB, ktoré sú v AGF-Servis Vráble a AGF Bratislava. Všetky databázy musia byť v okamžiku zavedenia replikácií zhodné. Najlepšie sa toho docieli off-line rozkopírovaním databázových súborov.

 

Vytvorenie subskripcií

Subskripciami sa rozumie priradenie publikácií konkrétnym vzdialeným užívateľom. Akonáhle je subskripcia odštartovaná, sú sledované všetky zmeny do tabuliek popísaných v príslušnej publikácii.

 

Řešení

Princíp vytvorenia novej konsolidovanej DB (KDB) spočíva v tom, že sa zo starej KDB zoberú obsahy tabuliek, ktoré sa nereplikujú zo vzdialených DB. V ďalšom kroku sa zo všetkých vzdialených DB zoberú obsahy tabuliek, ktoré sa replikujú do KDB. Pretože je nutné zachovať kontinuálnosť replikačného procesu, je nutné, aby medzi poslednou replikáciou na vzdialenej DB a odberom dát z nej neboli vytvorené žiadne dáta. To je najlepšie zaistiť tak, že pred odberom dát sa replikácia vyvolá ručne, pričom sú všetci užívatelia odpojení.

Konkrétny postup

Na každej vzdialenej DB spustením tohto skriptu stiahnuť dáta, ktoré sa replikujú. Cesta výstupných súborov musí samozrejme existovať

 

select * from ovydfakthd ># c:\data\ovydfakthd.dat;

select * from ovydfaktit ># c:\data\ovydfaktit.dat;

select * from udokhd ># c:\data\udokhd.dat;

select * from udokit ># c:\data\udokit.dat;

select * from udokst ># c:\data\udokst.dat;

 

 

Zaistiť, že nebudú až do okamžiku zavedenia novej KDB automaticky spustené replikácie nad KDB a nad KDB nebude nikto pracovať.

Nahrať do DB dáta získané zo starej KDB z AGF Vráble. Možno k tomu použiť tento skript. Súbory odkazované v skripte musia samozrejme existovať.

input into ovydfakthd from C:\data\ovydfakthd.dat;

input into ovydfaktit from C:\data\ovydfaktit.dat;

input into udokhd from C:\data\udokhd.dat;

input into udokst from C:\data\udokst.dat;

input into udokit from C:\data\udokit.dat;

 

Na serveru vedľa ostrých dát vytvoriť podadresár a premiestniť do neho LOG súbor starej KDB. Dátový súbor starej KDB už nebudeme potrebovať

Opäť naštartovať v plnej miere sieťový databázový server a uvolniť automatické spúšťanie replikačného agenta.

 

Číslo databázy – bolo zmenené pre systémy odlúčených prevádzok pre replikácie databáz, aby bolo vymedzené na ktorej databáze je možné dáta obstarávať a to nasledovne:

7 – pre AGF Servis Vráble

5 – pre AGF Bratislava

Ohľadne správnej funkčnosti replikácií boli prenesené dáta splňujúce podmienku:

- Vybraté boli knihy: KVF, VZD, P11, P04, P05, B01, B05, B27, INT, P06(z danej knihy boli prenesené len saldokontné obraty z roku 2011)
-Pre knihu KVF sa brali dáta z rady 06, 42, 22 a 11
-Pre knihu VZD sa brali dáta z rady INT, ZT, ZB
-Pre knihu P11 sa brali dáta z rady PD11
-Pre knihu P04 sa brali dáta z rady PD04
-Pre knihu P05 sa brali dáta z rady PD05
-Pre knihu P06 sa brali dáta z rady PD06
-Pre knihu B01 sa brali dáta z rady BV01
-Pre knihu B05sa brali dáta z rady BV05
-Pre knihu B27 sa brali dáta z rady BV27
-Pre knihu INT sa brali dáta z rady KFP

 

Pre replikácie je použitý skript

// rev. 10.1.2012 - uprava aj vo Vrabloch

var

strRada, strAge : string ;

nDataId,nDen : integer;

strDovod: string;

begin

 //{

 // stavy pokladne len na vybranu pokladnu

 if Document='STAVY_POKL' then begin

   if (KeyData.ParamByName('sklad').AsString = 'MB01') and ( Pos(':2005',HostName) = 0 ) then CanSend := False

   else if (KeyData.ParamByName('sklad').AsString = 'SERV') and ( Pos(':2007',HostName) = 0 ) then CanSend := False;

 

 if not CanSend  then strDovod := 'cudzi sklad';

 

 end

 else

 //neodesílej saldokontní případy

 if Document='UDOKHD' then begin

   strRada := KeyData.ParamByName('rada').AsString;

   strAge := KeyData.ParamByName('age').AsString;

{   if Query('select first 1 from dba.udokit as i where i.obd=:obd and i.age=:age and i.rada=:rada and i.dokl=:dokl and exists(select * from dba.ukonta as k where k.id_konto=i.konto and k.saldo in (1,2))', [

        FormatDateTime('yyyy-mm-dd', KeyData.ParamByName('obd').AsDate),

        strAge,

        strRada,

        KeyData.ParamByName('id_dokl').AsInteger

       ]) = Null then CanSend := False

   else  begin}

      if (strAge <> 'KVF')        and (strAge <> 'VZD') and (strAge <> 'P11') and (strAge <> 'P04') and (strAge <> 'P05') and (strAge <> 'B01')

       and (strAge <> 'B05') and (strAge <> 'B27') and (strAge <> 'INT') then CanSend := False

    else begin

       if (strAge = 'KVF') and (strRada <> '06') and (strRada <> '42') and (strRada <> '22') and (strRada <> '11') then CanSend := False

         else if (strAge = 'VZD') and (strRada <> 'INT') and (strRada <> 'ZT') and (strRada <> 'ZB') then CanSend := False

         else if (strAge = 'P11') and (strRada <> 'PD11') then CanSend := False

       else if (strAge = 'P04') and (strRada <> 'PD04') then CanSend := False

       else if (strAge = 'P05') and (strRada <> 'PD05') then CanSend := False

       else if (strAge = 'B01') and (strRada <> 'BV01') then CanSend := False

       else if (strAge = 'B05') and (strRada <> 'BV05') then CanSend := False

       else if (strAge = 'B27') and (strRada <> 'BV27') then CanSend := False

       else if (strAge = 'INT') and (strRada <> 'KFP') then CanSend := False;

   end;

 

   if not CanSend  then strDovod := 'nepovolena age/rada ' + strAge + '/' + strRada;

 end

 else

 if (Document='UDOKIT') or ( Document='UDOKST') then begin

    if (Document='UDOKIT') then begin

     nDataId := KeyData.ParamByName('data_id').AsInteger;

           nDen := KeyData.ParamByName('id_den').AsInteger;

    end;

    if ( Document='UDOKST') then begin

           nDataId := KeyData.ParamByName('data_id').AsInteger;

           nDen := KeyData.ParamByName('den').AsInteger;

    end;

 

 {   if Query('select first 1 from dba.udokit as i where i.data_id=:data_id and i.id_den=:id_den and exists(select * from dba.ukonta as k where k.id_konto=i.konto and k.saldo in (1,2))', [

        nDataId, nDen ]) = Null then CanSend := False

    else  begin }

     if (Operation = 'I') and (Query('select first 1 from dba.udokit as i where i.data_id=:data_id and i.id_den=:id_den',[nDataId, nDen])) = null then

   begin

        // zaznam už neexistuje

        CanSend := False;

              strDovod := 'zaznam už neexistuje';

   end

     else

     if Query('select first 1 from dba.udokit as i where i.age <> ''KVF'' and i.age <> ''VZD'' and i.age <> ''P11'' and i.age <> ''P04'' ' +

                     ' and i.age <> ''P05'' and i.age <> ''B01'' and i.age <> ''B05'' and i.age <> ''B27'' and i.age <> ''INT'' and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

           else begin

       if Query('select first 1 from dba.udokit as i where i.age = ''KVF'' and i.rada not in (''06'',''42'',''22'',''11'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

         else if Query('select first 1 from dba.udokit as i where i.age = ''VZD'' and i.rada not in (''INT'',''ZT'',''ZB'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

           else if Query('select first 1 from dba.udokit as i where i.age = ''P11'' and i.rada not in (''PD11'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

           else if Query('select first 1 from dba.udokit as i where i.age = ''P04'' and i.rada not in (''PD04'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

           else if Query('select first 1 from dba.udokit as i where i.age = ''P05'' and i.rada not in (''PD05'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

           else if Query('select first 1 from dba.udokit as i where i.age = ''B01'' and i.rada not in (''BV01'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

           else if Query('select first 1 from dba.udokit as i where i.age = ''B05'' and i.rada not in (''BV05'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

           else if Query('select first 1 from dba.udokit as i where i.age = ''B27'' and i.rada not in (''BV27'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False

         else if Query('select first 1 from dba.udokit as i where i.age = ''INT'' and i.rada not in (''KFP'') and i.data_id=:data_id and i.id_den=:id_den',

                [nDataId, nDen]) <> Null then CanSend := False;

 

           if not CanSend  then strDovod := 'nepovolena age/rada';

    end;

 end

 else

 {if Document='UDOKST' then begin

   if Query('select first 1 from dba.udokit as i where i.age = ''KVF'' and i.rada in (''06'',''42'',''22'',''11'') and i.data_id=:data_id and i.id_den=:id_den', [

        KeyData.ParamByName('data_id').AsInteger,

        KeyData.ParamByName('den').AsInteger

       ]) <> Null then begin

   if Query('select first 1 from dba.udokit as i where i.data_id=:data_id and i.id_den=:den and exists(select * from dba.ukonta as k where k.id_konto=i.konto and k.saldo in (1,2))', [

        KeyData.ParamByName('data_id').AsInteger,

        KeyData.ParamByName('den').AsInteger

       ]) = Null then

     CanSend := False;

 end

   else

     CanSend := False;

 end

 else}

 if (Document='OVYDFAKTHD') or (Document='OVYDFAKTIT') then begin

   strRada := KeyData.ParamByName('rada_id').AsString;

   strAge := KeyData.ParamByName('age_id').AsString;

 {  if Query('select first 1 from dba.udokhd as h where h.obd=:obd_id and h.age=:age_id and h.rada=:rada_id and h.id_dokl=:dokl_id and exists(select * from dba.udokit as i where i.obd=h.obd and i.age=h.age and i.rada=h.rada and i.dokl=h.id_dokl and exists(select * from dba.ukonta as k where k.id_konto=i.konto and k.saldo in (1,2)))', [

        FormatDateTime('yyyy-mm-dd', KeyData.ParamByName('obd_id').AsDate),

        strAge,

        strRada,

        KeyData.ParamByName('dokl_id').AsInteger

       ]) = Null then CanSend := False

   else  begin}

    if (strAge <> 'KVF')        and (strAge <> 'VZD') and (strAge <> 'P11') and (strAge <> 'P04') and (strAge <> 'P05') and (strAge <> 'B01')

       and (strAge <> 'B05') and (strAge <> 'B27') and (strAge <> 'INT') then CanSend := False

    else begin

       if (strAge = 'KVF') and (strRada <> '06') and (strRada <> '42') and (strRada <> '22') and (strRada <> '11') then CanSend := False

         else if (strAge = 'VZD') and (strRada <> 'INT') and (strRada <> 'ZT') and (strRada <> 'ZB') then CanSend := False

         else if (strAge = 'P11') and (strRada <> 'PD11') then CanSend := False

       else if (strAge = 'P04') and (strRada <> 'PD04') then CanSend := False

       else if (strAge = 'P05') and (strRada <> 'PD05') then CanSend := False

       else if (strAge = 'B01') and (strRada <> 'BV01') then CanSend := False

       else if (strAge = 'B05') and (strRada <> 'BV05') then CanSend := False

       else if (strAge = 'B27') and (strRada <> 'BV27') then CanSend := False

       else if (strAge = 'INT') and (strRada <> 'KFP') then CanSend := False;

   end;

   if not CanSend  then strDovod := 'nepovolena age/rada ' + strAge + '/' + strRada;

 end;

 

 //zapiš zprávu do konzole o stornovaném odeslání

 if not CanSend then

   WriteMessageToAppLog(Format('Sending cancelled: DocID=%s, QueueID=%d, Pricina=%s', [Document, QueueID, strDovod]));

   //}

end.

 

Související témata