28

Nov

Transazioni, ACID, SOA & WS-AT…. comuni incomprensioni… una chiara spiegazione

Ciao a tuti

 

approfitto di questa occasione per fare una delle mie solite digressioni, questa volta sulle transazioni

 

Inizio con il dire che “transazione” è un modo di dire generico, quasi un diminutivo, di una frase ben più completa che è “transazione atomica”

Le due parole significano quindi “un insieme di comandi” (transazione), eseguiti in maniera “imprescindibile” (atomica)

Degli esempi tipici sono: ho una fattura composta da dettaglio (intestazioni, etc) e corpo (le voci)… se devo persistere su uno storage (un DB) questo insieme di cose, quasi certamente dovrò farlo in maniera transazionale, perché è assurdo pensare di persistere una fattura con qualche riga in meno del dovuto, per gli ovvi motivi

 

Una transazione è quindi un contenitore di comandi, che ha il compito di garantirne l’esecuzione atomica, e per farlo esegue più compiti (che quindi hanno dei costi in termini di infrastruttura e di risorse), che in genere possono essere riassunte in:

  1. le singole operazioni vengono eseguite
  2. viene analizzato il risultato delle singole operazioni
  3. se tutte danno esito positivo un comando di persistenza (in genere detto “commit”) della transazione viene eseguito per dare il verde a tutte le operazioni
  4. altrimenti, se una qualunque operazione ha dato esito negativo, tutte le operazioni vengono annullate (in gergo detto “rollback”)

 

 

ACID

Lo standard di definizione di una transazione è dato dall’acronimo ACID, che sta per:

Atomic: le operazioni contenute nella transazione sono imprescindibili, o tutte vanno a buon fine, o tutte vengono annullate al fallimento di una qualunque di esse

Consistent: le operazioni delle transazioni sottostanno al modello dati su cui vengono persistite (es sui DB referenziali, vengono rispettate tutte le constraint), se una qualunque operazione della transazione non è valida nei confronti del modello dati, tutta la transazione viene annullata

Isolated: ogni transazione, se eseguita in contesto concorrente con altre transazioni, deve essere isolata dalle altre in modo da garantire una esecuzione congrua dall’inizio fino alla fine dei comandi contenuti nella stessa transazione; è anche garantito che il fallimento di una transazione non influisca su altre transazioni in corso di esecuzione

Durable: l’engine che esegue la transazione si impegna a garantire il salvataggio dei dati (che viene dato quindi per certo) una volta richiesto il comando di persistenza di tutte le operazioni contenute nella transazione

 

All’interno di una transazione, va detto che esiste in gergo un “isolation level”, un livello di isolamento che configura il come la transazione interagisce con altre transazioni, come se e quanto vengano viste le modifiche in corso in una transazione da un’altra transazione, etc.. QUI è possibile averne una spiegazione.

 

Le transazioni in genere si eseguono nei confronti di un singolo motore di persistenza di dati (in genere un DB), ma anche una coda (queue, es. MSMQ), o altri sistemi

Le transazioni possono essere innestate (transazioni di transazioni), ed infine esistono anche transazioni distribuite, quelle che eseguono transazioni innestate nei confronti di più sistemi (es. 2 diversi database).

 

Nelle transazioni singole (verso un unico DBMS), esistono 2 approcci per implementare la transazione:

  1. Write-ahead logging: le operazioni di modifica (e)[in base al DBMS] i dati originali (in caso di update) vengono scritte su un file di log e non sul file primario del database. Questo garantisce il commit se tutto va bene, il rollback in caso di errore, il “redo” (secondo tentativo) in caso di BSOD del sistema o crash del DBMS. La pulizia del file di log è impostata sempre dal DBMS.
  2. Shadow-paging: i dati del DB vengono suddivisi in pagine. eventuali modifiche da persistere vengono scritte su una pagina a parte, e solo alla commit della transazione, la pagina viene accodata (in caso di insert), o sovrascritta (in caso di update), o rimossa (in caso di delete) dal file primario del DBMS

 

Per eseguire queste operazioni, i DBMS utilizzano dei LOCK, dei blocchi a vari livelli, impostati per sincronizzare l’accesso alle risorse

Se più connessioni al DB eseguono transazioni sulle stesse tabelle, il DB utilizzando i lock sulla tabella intera, su un gruppo di righe, o sulla singola riga, riesce a coordinare l’accesso a queste informazioni. Quale di questi lock usare, se usarli, etc, è scelto dal DBMS anche in base al livello di isolamento utilizzato

 

 

Transazioni distribuite

Differente è l’approccio utilizzato quando si utilizzano transazioni “distribuite”, che quindi agiscono su più sistemi (es. un software deve chiamare in contemporanea 2 diversi WebServices, o un WS ed un DB, o 2 diversi DB):

 

In questo caso l’approccio utilizzato principalmente è quello della cosidetta 2PC (two phase commit). Questa è in pratica l’ACID in ottica distribuita. La differenza è il fatto che tutte le operazioni vengono fatte nei confronti di sistemi, che poi in autonomia implementano la loro transazionalità, quindi ad esempio sql server fa il suo dentro di se, oracle il suo, e la transazione distribuita serve per coordinare i due nodi.

 

La 2PC è suddivisa in 2 fasi (dal nome si evinceva…)

  1. Voting phase: il coordinatore chiede a tutti i partecipanti la transazione (i sistemi) di fare il loro compito tornandone lo stato (successo, fallimento)
  2. Completion phase: il coordinatore analizza i risultati dei partecipanti (detti anche i Voti) e decide se mandare un messaggio di conferma a tutti i partecipanti, o di annullamento, se uno qualunque vota NO, o non vota (e va in timeout)

 

 

Nel realizzare WebServices transazionali, che utilizzino il protocollo SOAP, il supporto alla 2PC è dato dai protocolli WS-AT (AtomicTransaction) e WS-Coordination, dove il secondo è il protocollo della gestione del contesto distribuito (in pratica l’attivatore della transazione), ed il primo è un protocollo che virtualizza l’ACID tramite il contesto di coordinamento.

 

Infine va detto che la quasi totalità dei sistemi nel mondo Microsoft utilizza il Microsoft il DTC (distributed transaction coordinator) per eseguire RPC (remote procedure call) in maniera distribuita e transazionale tra i vari sistemi (es. SQL Server, WS SOAP, etc).

 

SOA & Transazioni

Non si può avere enterprise senza transazioni, e difficilmente lo si può avere senza SOA, quindi pensare che questi due pilastri dell’enterprise non possano coesistere è assurdo. Una transazione in un contesto SOA ha i seguenti risultati:

  1. Irrobustisce l’ambiente
  2. Rende l’ambiente a servizi più coeso (più fiducia in service-composition)
  3. Aumenta l’integrabilità di sistemi eterogenei facenti parte dello stesso ambiente a servizi
  4. Aumenta i costi di infrastruttura per il maggior numero di messaggi interscambiati

Ma, anche se il punto 4 è un “contro”, va ricordato uno dei principi (diciamo pure capisaldi) del SOA: “Service Composability”, che enuncia: "Services are effective composition participants, regardless of the size and complexity of the composition."

Il significato, secondo Thomas Erl, non è solo che i servizi devono poter essere in grado di essere composti tra di loro, essere richiamabili a cascata, etc, ma anche essere in grado di farlo, senza perdite in latenza, numero di messaggi processati, etc… quindi, pensare di poter fare SOA, senza la potenza e la capacità di gestire migliaia o milioni di messaggi è impossibile, e quindi si può dire che l’unico contro è in realtà incluso per definizione nelle specifiche del SOA stesso.

Comunque, riguardo ai principi, usare transazioni nel SOA apporta, secondo la mappatura dei principi del SOA di Erl, benefici ai seguenti principi:

  • Service Composability
  • Service Interoperability
  • Quality of service

Più precisamente: se una operazione di business è in (contiene una) transazione, questa definisce un contesto di coordinamento, e questi garantiscono funzionalità transazionali ai WebServices

 

Citando sempre Thomas Erl nel suo famoso libro “SOA Priciples of Service design”, al punto 6.4.5 leggiamo:

“Much of the transactional funciontality implemented in service-oriented solutions is done so among the components that execute an activity on behalf of a single service. However, as more services emerge within an organization and as service compositions become more commonplace, the need to move transaction boundaries into cross-service interaction scenarios increases. Being able to guarantee an outcome of an activity is a key part of enterprise-level computing, and atomic transactions therefore play an important role in ensuring quality of service.”

E continua:

Not only do atomic transactional capabilities lead to a robust execution environment for SOA activities, they promote interoperability when extented into integrated environments. This allows the scope of an activity to span different solutions built with different vendor platforms, while still being assured a guaranteed all-or-nothing outcome.

Assuming, of course, that WS-AtomicTransaction is supported by the affected applications, this option broadens the application of the two-phase commit protocol beyond traditional application boundaries (thus, supporting service interoperability).”

 

 

Transazioni & REST

Mi spiace, ma REST non supporta niente di quanto detto finora…

REST è un WebService puro, in pratica si rifà alla sicurezza del webserver, al caching del webserver… in pratica il protocollo non supporta quasi niente di suo visto che per quasi ogni cosa si poggia sul webserver (IIS nel mondo Microsoft), e visto che non possiamo richiamare pagine Html tramite HTTP in maniera transazionale, non possiamo nemmeno chiamarne API (WebApi, o chiamate REST che siano)

Infatti nelle specifiche di questo tipo di servizi è specificato di non usare transazioni, non usare sessioni, non usare stati… e per quel tipo di servizi è più che corretto! oltre che comunque una buona practice, sempre per quel tipo di servizi (quelli REST)…..

 

 

Saluto tutti i lettori che hanno avuto la voglia di leggere fin qui Sorriso

A presto

by Antonio Esposito on 11/28/2012