Eigen logica in triggers voor datasynchronisatiestatement voor meer gemak

Go to English version

Het synchronize-statement is uitgebreid met opties om eigen logica uit te voeren die in Invantive PSQL is geschreven. De PSQL-logica wordt uitgevoerd wanneer een gebeurtenis wordt getriggerd (insert, update en/of delete). Aparte eigen triggerlogica kan worden gespecificeerd om te worden uitgevoerd voor en na de gebeurtenis, en in plaats van de gebeurtenis.

Het gebruik van eigen logica voor het triggeren van gebeurtenissen heeft de volgende voordelen in complexe datasynchronisatie- of data-integratiescenario’s, waardoor de bruikbaarheid als one-stop-integratieplatform voor bedrijfsgegevens toeneemt:

  • vereenvoudigen data-integratie taken,
  • verminderen hoeveelheid werk nodig is voor complexe synchronisatietaken
  • verhogen de bruikbaarheid, controleerbaarheid en betrouwbaarheid.

De nieuwe functionaliteit is beschikbaar vanaf release 22.1 BETA en in de toekomstige productierelease.

Bestaande synchronisatiefunctionaliteit

De release 22.0 datasynchronisatiefunctionaliteit van synchronize blijft volledig gehandhaafd en ondersteund.

Met synchronize kan een enkel SQL-statement unidirectioneel of bidirectioneel de inhoud van twee tabellen vergelijken en gelijktrekken. Dit gelijktrekken door datasynchronisatie zorgt ervoor dat de waarden in de tabel voor identiek genaamde kolommen overeenkomen (rekening houdend met kleine verschillen in gegevensformaat zoals long en short). Voorbeelden voor datasynchronisatie zijn beschikbaar in:

De functionaliteit van statements blijft behouden. Synchronize blijft de voorkeursoplossing voor batchgewijze datasynchronisatie. Gebruik de andere Invantive SQL middelen voor real-time datasynchronisatie, zoals Invantive App Online voor het opvangen van webhookevents en uitvoeren van acties.

Uitdagingen voor datasynchronisatie

Het synchroniseren van gegevens is een krachtig concept voor data-integratie. Het datasynchronisatieproces kan echter extra eisen stellen boven de mogelijkheden van release 22.0, zoals verschillende tabellen om van te lezen en te schrijven, een optie voor dry-run en/of actie-auditing.

Verschillende tabellen om uit te lezen en te schrijven

Een typische uitdaging voor datasynchronisatietools is wanneer de tabel (of API) die moet worden aangepast anders is dan de tabel waarmee de gegevens worden vergeleken. Sommige platforms hebben bijvoorbeeld (relatief trage) tabellen die insert toestaan, maar waar de vergelijking gaat via een geoptimaliseerde read-only versie. Een populair voorbeeld hiervan zijn de Exact Online transactietabellen; terwijl de (alleen-lezen) *Incremental tabellen gemakkelijk grote datavolumes zoals miljoenen transacties in minuten teruggeven, maar waarbij de lees/schrijf-versie beperkt is tot maximaal 60 rijen per seconde en een cumulatief leesgebruik van maximaal 300.000 rijen per dag.

Met behulp van aangepaste logica voor het triggeren van gebeurtenissen, kan de synchronisatie lezen uit een incrementele tabel zoals AccountsIncremental en wijzigingen aanbrengen via de (langzamere) Accounts-tabel. Dit zal tot honderden keren sneller lopen, terwijl het de belasting vermindert en de schaalbaarheid in grote omgevingen beter wordt.

Natuurlijk is in dit scenario aangenomen dat beide tabellen na verloop van tijd steeds meer identieke gegevens bevatten (en natuurlijk dezelfde gegevens direct na afloop van de synchronisatie). De vermindering van het aantal benodigde wijzigingen vermindert de geamortiseerde looptijd aanzienlijk door de aangepaste logica.

Dry-run en actie-auditing

Een andere uitdaging voor synchronisatietools voor bedrijfsgegevens is dat de synchronisatie prima verloopt, maar dat het door de complexiteit van het synchronisatieproces moeilijk is om het eigenlijke proces te controleren. Of erger nog, soms moet de lijst met wijzigingen worden afgetekend voordat de eigenlijke synchronisatie kan plaatsvinden.

Door aangepaste code te gebruiken om gegevens te synchroniseren kunnen de wijzigingen vooraf worden getoond en kan gemakkelijk een audittrail van de feitelijke wijzigingen worden vastgelegd, zelfs wanneer het doelplatform geen auditfuncties heeft.

Voorbeeld van aangepaste logica

Het synchronize-statement synchroniseert de brontabel met de doeltabel via eigen logica voor alle triggers. Er zijn negen mogelijke triggers op een synchronisatie, namelijk elke combinatie van:

  • gebeurtenis: insert, update en delete,
  • uitvoeringsmoment voor, in plaats van en na de gebeurtenis.

Aan het einde van het synchronize-statement worden na het sleutelwoord triggers de triggers gespecificeerd als het uitvoeringsmoment en de gebeurtenis. Bijvoorbeeld, de volgende logica wordt uitgevoerd voorafgaand een insert:

synchronize
...
triggers
before insert
begin
  ... code ...
end;

De PSQL-code kan verwijzen naar de oude en nieuwe waardes via, respectievelijk, het voorvoegsel :old en :new. Merk op dat :old en :new afhankelijk zijn van de synchronisatierichting. In het bijzonder voor bidirectionele synchronisatie kunnen de bron- en doel-tabel telkens weer anders zijn. Kolommen niet beschikbaar in de geselecteerde bron of doel met :old en :new verwijzingen evalueren naar null.

Wanneer een tabel bijvoorbeeld de kolom name bevat, zal de volgende code wijzigingen van de naam afdrukken:

synchronize
...
triggers
before update
begin
  if ( :old.name is null and :new.name is not null )
     or
     ( :old.name is not null and :new.name is null )
     or
     :old.name != :new.name
  then
    dbms_output.put_line('Name is changed from ' || :old.name || ' to ' || :new.name || '.');
  end if;
end;

Voorbeeld van eigen logica

Het onderstaande voorbeeld synchroniseert de bron- naar de doeltabel met behulp van triggers. Maak en vul de tabellen eerst zoals getoond aan het einde van dit artikel voordat u gegevens synchroniseert.

Het resultaat van de uitvoering in dit geval is altijd:

voor insert met ID A
in plaats van insert met ID A: 5
na insert met ID A
voor update met ID B
in plaats van update met ID B: 4 → 7
na update met ID B

Datasynchronisatiestatement:

sync source@inmemorystorage
to   target@inmemorystorage
with insert or update or delete
identified
by   dummy_string
triggers
before insert
begin
  dbms_output.put_line('before insert on ID ' || :new.dummy_string);
end
instead of insert
begin
  dbms_output.put_line('instead of insert on ID ' || :new.dummy_string || ': ' || :new.dummy_int32);
end
after insert
begin
  dbms_output.put_line('after insert on ID ' || :new.dummy_string);
end
before update
begin
  dbms_output.put_line('before update on ID ' || :new.dummy_string);
end
instead of update
begin
  dbms_output.put_line('instead of update on ID ' || :new.dummy_string || ': ' || :old.dummy_int32 || ' -> ' || :new.dummy_int32);
end
after update
begin
  dbms_output.put_line('after update on ID ' || :new.dummy_string);
end
before delete
begin
  dbms_output.put_line('before delete on ID ' || :old.dummy_string);
end
instead of delete
begin
  dbms_output.put_line('instead of delete on ID ' || :old.dummy_string);
end
after delete
begin
  dbms_output.put_line('after delete on ID ' || :old.dummy_string);
end

Voorbeeld tabelcreatie

Gelieve ter voorbereiding op de synchronisatie met de volgende SQL-code twee tabellen aan te maken (source en target) met de volgende inhoud.

Tabel source

dummy_string dummy_int32 dummy_datetime
A 5 now
B 7 now
C 9 now

Tabel Target

dummy_string dummy_int32
B 4
C 9

Code voor Tabellen

create or replace table source@inmemorystorage
as
select 5     dummy_int32
,      now() dummy_datetime
,      'A'   dummy_string
union all
select 7     dummy_int32
,      now() dummy_datetime
,      'B'   dummy_string
union all
select 9     dummy_int32
,      now() dummy_datetime
,      'C'   dummy_string

create or replace table target@inmemorystorage
as
select 'B'   dummy_string
,      4     dummy_int32
union all
select 'C'   dummy_string
,      9     dummy_int32

Bulk laden

In het algemeen worden de triggers met aangepaste logica per rij aangeroepen, dus als er twee rijen moeten worden bijgewerkt, is de volgorde van aanroepen:

  1. voor update rij 1
  2. (in plaats van) update rij 1
  3. na update rij 1
  4. voor update rij 2
  5. (in plaats van) update rij 2
  6. na update rij 2

Invantive SQL biedt echter ondersteuning voor bulkladen op verschillende platformen zoals SQL Server, PostgreSQL en Oracle RDBMS (native driver). In dat geval worden inserts gebundeld in batches. De grootte van elke batch kan worden gespecificeerd met het batchsize sleutelwoord (documentatie).

Elke batch wordt typisch verwerkt als een ondeelbare eenheid, maar het hoeft geen atomaire transactie te zijn. Bij mislukking zullen één of meer rijen in de batch niet geladen worden en andere wel. In het algemeen is het onmogelijk te achterhalen welke rijen mislukt en/of geldig zijn zonder de uiteindelijke database-inhoud opnieuw te lezen.

Bij geen gebruik van een in plaats van-trigger en bulkladen met een batchgrootte groter dan 1, zal de aanroepvolgorde voor twee rijen die worden ingevoegd zijn:

  1. voor insert rij 1
  2. voor insert rij 2
  3. bulk insert rij 1 en 2
  4. na insert rij 1
  5. na insert rij 2

Wanneer er meer rijen te laden zijn dan de batchgrootte toelaat, zal de aanroepvolgorde dezelfde zijn, maar alleen voor de rijen in een batch. Latere batches zullen de volgorde vanaf het begin herhalen met andere rijen.