UGISS Community

Il sito della community dello User Group Italiano di SQL Server
Welcome to UGISS Community Sign in | Join | Help
in Search

Alessandro Alpi's blog

Parliamo di integration services e non solo..

marzo 2008 - Posts

  • [SSIS] I Checkpoint - Workaround Foreach Loop

     In questo mio post, definivo le caratteristiche dei checkpoint ed un'introduzione alla funzionalità di SSIS.

    Vi sono casi particolari, come quello indicato in questo thread su microsoft.public.it.sql, che necessitano di alcuni workaround per portare dalla propria parte lo svantaggio che il For each Loop container ha con i checkpoint .  Nel thread indicato, vi è una semplice richiesta. Ottenere un Sequence container che, in caso di errore, non rispetti le semplici condizioni di checkpoint e che quindi si riavvii per intero. Comportandosi naturalmente, al contrario, il task che ha generato l'errore all'interno del contenitore è quello che verrà eseguito per primo al riavvio, ignorando i precedenti.

    Il workaround è semplice:

    - impostare la proprietà FailPackageOnFailure a false in TUTTI i task interni ai sequence container
    - Aggiungere in ogni sequence container un Foreach Loop container
    - Impostare il Foreach Loop container con l'enumeratore "Item"
    - Aggiungere sotto una colonna di tipo intero ad esempio (un item con un qualunque valore)
    - Impostare la proprietà FailPackageOnFailure del Foreach Loop a true
    - Spostare tutti i task che erano nel sequence container all'interno del Foreach Loop container
    - Impostare la proprietà FailParentOnFailure di ogni task (di primo livello) interno al Loop a true
    - Imposta la proprietà CheckpointUsage del package a IfExists e la FailPackageOnFailure del package a false (con CheckpointFileName = "path/file.chk" e SaveCheckpoints = true)

    La chiave è quella di sfruttare al meglio lo svantaggio del foreach

    In materia di checkpoint (e non solo), consiglio un video di Brian Knight, su jumpstartTV. Non fatevi ingannare dalla signora prima del video di Brian, è solo pubblicità; non c'entra con SQL Server

    Stay tuned!
  • [SSIS] I Checkpoint

    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!