75 PDO5 transazioni

Immaginiamo di dover fare un po’ di pulizia, cancellando i questionari più vecchi di tot anni e poi cancellare gli utenti iscritti prima di tale data e con zero privi di questionari svolti.
Sarebbero 2 operazioni di delete, la cancellazione questionari e quella utenti. Supponiamo che per qualsiasi motivo lo script inizia e prima di terminare si blocca, si tratta di casi chiamati di perdita di consistenza a causa di operazioni non completate. Il meccanismo transazionale è stato introdotto per ovviare a tali inconvenienti. Le transazioni sono uno script di comandi SQL per cui il sistema che le esegue assicura che o tutte quelle operazioni dello script vengano eseguite correttamente, oppure che è in grado di accorgersi dell’anomalia riportando la situazione allo stato precedente all’esecuzione (roll back del database).
Saltando la solita parte di inclusione e connessione vediamo ora la parte delle transaction della nuova pagina transazione_PDO.php. Il supporto per le transazione di MySQL supporta perfettamente il try/catch del php.
Iniziamo una transazione col metodo beginTransaction:

try
{
   $conn->beginTransaction();

Prepariamo poi il comando che canchella i questionari anteriori al primo gennaio 2002:

$comandoSQL ="delete from questionari_svolti where fine<'2002-01-01'";

Lo eseguiamo col metodo exec, da usare quando non ci si aspetta un ritorno di risultato di righe.

Stessa cosa per gli utenti:

$comandoSQL = "delete from users where iduser not in ".
    "(select fkuser from questionari_svolti)";
$conn->exec($comandoSQL);

Tra il primo comando e il secondo potrebbere verificarsi una anomalia che blocca l’esecuzione, avendo istanziato una transazione, i dati sul database non vengono cancellati permanentemente, fino a quando non viene eseguita la conferma tramite il comando commit:

$conn->commit();

Se viene eseguita questa riga, le operazioni sono andate a buon fine e le modifiche vengono rese permanenti. Se avviene l’anomalia, il blocco try si interrompe, insieme al comando commit e si passa al blocco catch:

catch (Exception $e)
{
    $conn->rollBack();
    echo "Pulizia archivi fallita ".$nl;

    die();
}

Con il rollback il database viene riportato allo stato precedente.

Di seguito il codice completo della pagina:

<?php
include($_SERVER['DOCUMENT_ROOT']."/fagtest/my_include/setup_con_DB.php");

//recupero credenziali da file ESTERNO alla cartella pubblica del sito


try
{
    //CONNESSIONE
    $conn = new PDO("mysql:host=localhost;dbname={$accessData['dbname']}",
        $accessData['username'],$accessData['password']);
}

catch (PDOException $e)
{
    echo $e->getMessage() . "<br/>";
    echo "Connessione al server fallita. Impossibile procedere. Contattare ...";
    die();
}

//ATTIVAZIONE ECCEZIONI PER METODO QUERY
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try
{
    $conn->beginTransaction();

    $comandoSQL ="delete from questionari_svolti where fine<'2002-01-01'";
    $conn->exec($comandoSQL);

    //dopo l'esecuzione del precedente comando e quella del seguente
    //potrebbere verificarsi una anomalia che blocca l'esecuzione
    //sul server ...

    //verrebbe sollevata l'eccezione, saltato il commit e comandato il rollback

    //controlli ...
    /*          $errore=true;
                    if($errore)
                      $conn->rollBack(); //annulliamo le operazioni precedenti
        else
                    {
                      $comandoSQL = "delete from users where iduser not in ".
                                  "(select fkuser from questionari_svolti)";
                      $conn->exec($comandoSQL);

                //se siamo arrivati qui rendiamo permanenti le modifiche
                      $conn->commit();
                    }
    */

    $comandoSQL = "delete from users where iduser not in ".
        "(select fkuser from questionari_svolti)";
    $conn->exec($comandoSQL);

    //se siamo arrivati qui rendiamo permanenti le modifiche
    $conn->commit();


}

catch (Exception $e)
{
    $conn->rollBack();
    echo "Pulizia archivi fallita ".$nl;

    die();
}


//CHIUDIAMO LA CONNESSIONE E LIBERIAMO LE RISORSE OCCUPATE ...
$conn=null;