SSIS 2005 possiede una importante funzionalità, quella dei Checkpoint. Ogni pacchetto, opportunamente configurato, può creare e gestire un checkpoint file,
in grado di memorizzare gli stati del package a runtime. Detto in
parole povere, il checkpoint consente di ripristinare una situazione
corrispondente al verificarsi di un errore.
Ogni volta che si
verifica un errore il file di checkpoint viene scritto ed un
particolare record in formato xml viene accodato agli eventuali
precedenti. Una volta che il pacchetto termina l'esecuzione con
successo cancella il file di checkpoint, per ripristinare lo stato
iniziale di esecuzione.
Ovviamente una tecnologia semplice come
questa può risolverci alcuni problemi ed alleggerire in generale il
carico dei server o della rete inclusa nella logica di
importazione/trasformazione.
Quali sono i vantaggi dei checkpoint?
-
Come già detto, evitare di ripetere alcune operazioni. Immaginiamo
infatti particolari inserimenti o modifiche che non devono essere
ripetuti. In questo caso possiamo evitare di scrivere logiche di
controllo potenzialmente pesanti.
- Evitare di ricaricare grandi quantità di dati, riducendo l'eventuale carico di rete congiunto
- Evitare di ricaricare file di grandi dimensioni, riducendo anche qui il carico di rete
- Evitare di ripetere eventuali aggregazioni
Il record scritto nel file di checkpoint contiene anche i valori correnti delle variabili, escluse quelle reference type (object).
L'unità più piccola che può essere riavviata è il task (o meglio l'host container invisibile che lo contiene). Anche alcuni contenitori come il Sequence Container sono
considerati come unità riavviabili. Mentre però in un Sequence
Container il task che ha generato l'errore dirige il riavvio, è
necessario fare particolare attenzione al For each loop container.
Infatti, con un errore, la riesecuzione riparte da zero e quindi
l'enumeratore riparte dal primo elemento della collezione ciclata. Non
è possibile riprendere da una particolare iterazione. Questo può essere
un comportamento non voluto e quindi uno degli svantaggi più evidenti del Foreach loop container.
Immaginate ad esempio un ciclo foreach che esegue n transazioni (ad
esempio n inserimenti). In caso di errore durante un inserimento
diverso dal primo il package è pensato per scrivere sul checkpoint che
il ciclo è andato in errore. La riesecuzione forza tutti i cicli del
container come "da rieseguire", ripartendo dal primo. Questo può
portare un vero e proprio errore anche sulla qualità del dato.
Ci sono tre variabili delle quali tenere conto durante l'impostazione di un package per supportare i checkpoint:
- CheckpointFileName
- CheckpointUsage
- SaveCheckpoints
La
prima definisce il nome del file per il checkpoint (non vi è la
possibilità di impostare un connection manager, ma per rendere dinamico
il percorso è sufficiente definire un'Expression che imposta il nome
stesso). La seconda è un enum che definisce qual è l'utilizzo del
checkpoint file e la terza, se valorizzata a true, impone il
salvataggio del checkpoint per ripartire dall'ultimo errore incontrato.
CheckpointUsage può assumere a sua volta tre valori:
- Never, Il package non utilizza il file dei checkpoint
- Always, Il package usa sempre il file del chackpoint e se non lo trova restituisce errore
- IfExists, Il package utilizza il file se esiste. In caso contrario prosegue l'esecuzione
Altra proprietà da utilizzare in concomitanza con la definizione dei checkpoint è la FailPackageOnFailure.
Questa proprietà, se valorizzata a true ed in caso di errore del task
che la possiede, scatena l'evento per la scrittura del checkpoint sul
file.
Ecco come si presenta un file di checkpoint:
<DTS:Checkpoint xmlns:DTS="www.microsoft.com/SqlServer/Dts" DTS:PackageID="{CF9B140D-67D3-4D86-AF08-87C2C1DCBA3A}">
<DTS:Variables DTS:ContID="{CF9B140D-67D3-4D86-AF08-87C2C1DCBA3A}">
<DTS:Variable>
<DTS:Property DTS:Name="Expression"></DTS:Property>
<DTS:Property DTS:Name="EvaluateAsExpression">0</DTS:Property>
<DTS:Property DTS:Name="Namespace">User</DTS:Property>
<DTS:Property DTS:Name="ReadOnly">0</DTS:Property>
<DTS:Property DTS:Name="RaiseChangedEvent">0</DTS:Property>
<DTS:VariableValue DTS:DataType="3">0</DTS:VariableValue>
<DTS:Property DTS:Name="ObjectName">var1</DTS:Property>
<DTS:Property DTS:Name="DTSID">{8758E0D8-E786-4497-BE6F-8146F9D6FBA3}</DTS:Property>
<DTS:Property DTS:Name="Description"></DTS:Property>
<DTS:Property DTS:Name="CreationName"></DTS:Property>
</DTS:Variable>
</DTS:Variables>
<DTS:Container DTS:ContID="{005F0094-ED1D-41C5-88BF-F6E6E13D1BBF}" DTS:Result="0" DTS:PrecedenceMap=""/>
</DTS:Checkpoint>
Si tratta di un XML file che contiene le informazioni leggibili dei
task che sono andati in errore. Molto semplice da leggere e da capire.
Una sezione di intestazione del checkpoint, un eventuale elenco di
variabili e le relative proprietà, il container di riferimento, ecc.
Ho
trovato questa funzionalità estremamente utile nei casi di scratch
load. Poter fermare il package in caso di errore mentre si stanno
caricando grandi quantità di dati da enormi file di testo, con la
garanzia di poter ripartire da un determinato punto, è del tutto
vantaggioso.
Stay tuned!
