Supporto - consigli e chiarimenti per utilizzo transazioni ...

Kelly

Utente Attivo
5 Set 2008
112
1
18
Salve....


Avrei bisogno di un supporto per capire l'utilizzo delle transazioni, ringrazi in anticipo.

Per evitare il blocco intero della tabella (lock) ho scelto le transazioni per gestire l'eventuale aggiornamento contemporaneo di un record da parte di 2 utenti.

Quindi, con una select visualizzo in una tabella i record che hanno il medesimo codice cliente.

Codice:
$resultrigheord = mysqli_query($connessione,"start transaction")
or die ("impossibile avviare la transazione");
$queryselect .= "select  * FROM insart WHERE CODCLI = '$codcli' AND CODDEST = '$coddest'";
$resultrigheord = mysqli_query($connessione,$queryselect);
if(!$resultrigheord)
die(mysqli_error($connessione));
mysqli_close;

Invece l'aggiornamento del record insseguito ad una modifica lo gestisco con una query update
Codice:
$queryEdit = "UPDATE insart SET QT = '$qt', NOTEART = '$noteart' WHERE ID = $pIndice";
$resultedit = mysqli_query($connessione,$queryEdit);
$resultcommit= mysqli_query($connessione,"COMMIT")
or die ('imossibile eseguire la modifica');
	 
if(!$resultedit)
die(mysqli_error($connessione));

Nel mio esempio, inizio la transazione a partire dalla select ma se l'utente
non esegue alcuna modifica lascio la transazione aperta, e invece io credo che debba chiudere il cerchio, giusto? quindi mi chiedevo se è più corretto utilizzare sia lo start transaction che il commit nella query di aggiornamento.

Un altro concetto da chiarire è : lo start transation se non blocca i record che cosa fa tecnicamente?
Che prove devo fare per capire che il codice scritto mi gestisce l'accesso contemporaneo della modifica?
ad esempio non mi da errore?

grazie infinite
 

marino51

Utente Attivo
28 Feb 2013
3.039
192
63
Lombardia
le transazioni hanno lo scopo di gestire le operazioni che avvengo in sequenza
ovvero permettono di lasciare il db consistente nel caso giustappunto una transazione non vada a buon fine
nulla a che vedere con l'accesso contemporaneo che devi gestire con "lock"
(non ho conoscenze mysql quindi non ti suggerisco nulla)
mentre ti riporto un esempio di transazione, giusto per avere una visione

PHP:
  $OPdbresult = $db->begin_transaction();
  if ($OPdbresult)
  {
    $sql = "insert into caratteristiche  ....";

    $OPdbresult = $db->queryM($sql, array($c1, $c2, $c3, $c4)); 
    if ($OPdbresult)
    {
      $OPdbresult = check_DB(); // verifica che il record sia stato veramente inserito (non mi fido mai)
      if ($OPdbresult)
      {
        $sql = "insert into matrice .....";

        $OPdbresult = $db->queryM($sql, array($c1, $c2));
      }
    }
    if ($OPdbresult) $db->commit_transaction();
    else             $db->rollback_transaction();
  }
  return $OPdbresult;
}
ciao
Marino
 

flameseeker

Utente Attivo
27 Nov 2013
699
0
0
Teoria

Le transazioni servono ad eseguire in un database diverse query in modo simultaneo.
Questa esigenza nasce per poter prevenire e gestire facilmente le operazioni di ripristino dei dati nel caso un ipotetica procedura di aggiornamento fallisca prima del suo completamento, comportando così l'archiviazione di dati incoerenti nelle nostre tabelle.

Esempio pratico del problema

Ti pongo un esempio pratico per mostrarti la problematica, una procedura di acquisto in un possibile sito e-commerce.

Nel momento in cui un utente vuole acquistare il materiale riposto nel suo carrello, la nostra procedura deve svolgere queste operazioni:
  1. Selezionare il credito disponibile dell'utente
  2. Selezionare l'importo totale da pagare
  3. Eseguire lato codice i controlli necessari
  4. Segnare i prodotti come acquistati
  5. Aggiornare l'importo dell'utente

Se questo flusso, a causa di un errore, dovesse interrompersi tra il quarto e il quinto passaggio ci ritroveremmo che l'utente potrebbe trovarsi il materiale acquistato ma senza che gli sia stato detratto l'importo.
Questo problema si risolve grazie alle transazioni.

Come funziona una transazione

All'interno di una transazione le tue query vengono convalidate nel database unicamente quando richiami l'istruzione di commit.

Codice:
START TRANSACTION;
    -- Prepariamo le nostre operazioni
    SELECT ...
    UPDATE ....
    INSERT ....

-- tutto ok, convalidiamo le query
COMMIT;

La grande utilità di una transazione sta inoltre nel fatto che se dovesse intervenire un errore puoi annullare per intero tutte le query del blocco:

Codice:
START TRANSACTION;
    -- Prepariamo le nostre operazioni
    SELECT ...
    UPDATE ....
    INSERT ....

-- ho trovato un errore, non confermo le modifiche sul db
ROLLBACK;

E' chiaro che, finché non viene mandato il commit, se un altro utente richiede un dato da una tabella (magari quella su cui stiamo facendo un update) continuerà a leggere quello vecchio, anche se la transazione è già stata avviata.

Come fare quindi per impedire ad un utente di leggere un dato fino a che non finisco le operazioni sullo stesso ?

Lock delle righe

Il lock è uno strumento importante, senza di esso (tornando all'esempio dell'e-commerce) se un utente riuscisse ad avviare col giusto tempismo due transazioni differenti nello stesso momento, entrambe le transazioni useranno lo stesso importo dell'utente come riferimento per scalargli l'importo e l'ultima transazione eseguita gli sottrarrà quindi soltanto l'importo per i prodotti elaborati in quella transazione, lasciando che l'utente riceva degli "omaggi" non previsti dal sistema.

Mysql ci mette a disposizione la possibilità di realizzare un lock sulle righe lette tramite l'istruzione FOR UPDATE (quindi non sull'intera tabella).
Tale clausola fa si che gli altri processi che cercano di utilizzare il dato o i dati sotto lock saranno messi in attesa finché non concludiamo l'operazione.

Tornando al nostro esempio di procedura di acquisto:
Codice:
START TRANSACTION;
    -- Leggiamo l'importo utente
    SELECT importo FROM utenti WHERE utente = 'riferimento' FOR UPDATE;
    -- Facciamo le nostre operazioni di controllo
    ....
    -- Aggiorniamo l'importo utente
    UPDATE utenti SET importo = 'nuovo importo' WHERE utente = 'riferimento';

-- tutto ok, confermiamo l'esecuzione delle query sul database
COMMIT;


Mysqli

Il modulo mysqli di php mette a disposizione diverse istruzioni che permettono di gestire la transazione senza richiedere manualmente la query "start transaction".

Un esempio di transazione con queste istruzioni, sfruttando l'esempio di prima, potrebbe essere:
PHP:
// Iniziamo la nostra transazione
mysqli_autocommit($link, false);

$query = mysqli_query($link, "SELECT importo FROM utenti WHERE utente = 'riferimento' FOR UPDATE");

// se la query riesce, andiamo avanti
if ($query !== false) {

    // altre operazioni di controllo..

    // Scriviamo il dato
    if (mysqli_query($link, "UPDATE utenti SET importo = 'nuovo importo' WHERE utente = 'riferimento'") !== false) {
        
        // convalidiamo tutta la transazione
        mysqli_commit($link);

    } else {
        // errori nella query, rollback
        mysqli_rollback($link);
    }

} else {
    // se la query non riesce, diamo rollback delle operazioni
    mysqli_rollback($link);
}

// Riportiamo mysql al suo comportamento iniziale
mysqli_autocommit($link, true);


Il tuo caso specifico..

C'è da capire una cosa, la tua query di select ha come unica finalità quello di mostrare il dato nella pagina dell'utente ? Perché in questo caso non occorre mettere questa query sotto una transazione.

L'unico punto in cui devi adoperare una transazione è sulla modifica del dato e se vuoi gestire accessi contemporanei alla sua modifica dei impiegare il lock come ti ho illustrato.

Se nella tua pagina, cominci eseguendo la query di select (che userai anche per far visualizzare il dato) e successivamente controllando una variabile decidi se l'utente deve eseguire un update ti consiglio di ripetere la select nella transazione al fine di ottenere il lock ed effettuare in tranquillità l'update (oltre che a prendere sicuramente i dati più aggiornati nel caso si sia in attesa di un altra modifica sullo stesso).
 

Kelly

Utente Attivo
5 Set 2008
112
1
18
Supporto - consigli e chiarimenti per utilizzo transazioni ...

Ahhh ok.....
quindi potrei utilizzare le transazioni ad esempio nel caso di più query a catena avviate ad esempio da un utente,
e tutto per garantire che tutti i dati siano coerenti dall'inizio alla fine della transazione.
Ho capito bene?

Ho quindi questa domanda da farti anche se non usi mysql la logica dovrebbe essere la stessa....

Supponiamo che il cliente per fare l'ordine ha un codice cliente,
e supponiamo anche che il cliente in questione ha 2 negozi quindi con lo stesso codice cliente,
anche se la possibilità è piuttosto remota, potrebbe verificarsi un accesso contemporaneo su quell'articolo per la modifica!
Quindi cosa decido....
1) di bloccare la tabella per evitare confusione sui dati, inserendo ahimè tempi di attesa per i clienti
oppure
2) visto che la possibilità è remota decido di non utilizzare il lock, lasciando le cose come stanno?


grazie mille






le transazioni hanno lo scopo di gestire le operazioni che avvengo in sequenza
ovvero permettono di lasciare il db consistente nel caso giustappunto una transazione non vada a buon fine
nulla a che vedere con l'accesso contemporaneo che devi gestire con "lock"
(non ho conoscenze mysql quindi non ti suggerisco nulla)
mentre ti riporto un esempio di transazione, giusto per avere una visione

PHP:
  $OPdbresult = $db->begin_transaction();
  if ($OPdbresult)
  {
    $sql = "insert into caratteristiche  ....";

    $OPdbresult = $db->queryM($sql, array($c1, $c2, $c3, $c4)); 
    if ($OPdbresult)
    {
      $OPdbresult = check_DB(); // verifica che il record sia stato veramente inserito (non mi fido mai)
      if ($OPdbresult)
      {
        $sql = "insert into matrice .....";

        $OPdbresult = $db->queryM($sql, array($c1, $c2));
      }
    }
    if ($OPdbresult) $db->commit_transaction();
    else             $db->rollback_transaction();
  }
  return $OPdbresult;
}
ciao
Marino
 

Kelly

Utente Attivo
5 Set 2008
112
1
18
Supporto - consigli e chiarimenti per utilizzo transazioni ...

Graaaazieeeeeeee

Ora è tutto molto molto più chiaro...:love:
Nel mio caso in effetti non ho bisogno di transizioni, e confermo che la prima select che utilizzo mi serve per visualizzare i dati.

Quindi tenuto conto di tutto il mio codice potrebbe essere:

appena entro nella pagina visualizzo tutte le righe dell'ordine di quel cliente utilizzando una semplice select
Codice:
   $queryselect .= "select  * FROM insart WHERE CODCLI = '$codcli' AND CODDEST = '$coddest'";
   $resultrigheord = mysqli_query($connessione,$queryselect);
   if(!$resultrigheord)
     die(mysqli_error($connessione));
Invece quando clicco per modificare una delle righe dell'ordine avrò questo codice, e grazie all'utilizzo del FOR UPDATE blocco quel recordset. (ma in questo caso devo per forza inizializzare la transazione e finire con il commit perchè funzioni il blocco dei record selezionati?)
ho capito?

Codice:
        $queryFORUPDATE = "SELECT QT, NOTE from insart WHERE ID = $pIndice FOR UPDATE";
	$resultFORUPDATE = mysqli_query($connessione,$queryFORUPDATE);
	if(!$resultFORUPDATE) 
	die(mysqli_error($connessione));
	
        $queryEdit = "UPDATE insart SET QT = '$qt', NOTEART = '$noteart' WHERE ID = $pIndice";
	$resultedit = mysqli_query($connessione,$queryEdit);
	if(!$resultedit) 
	die(mysqli_error($connessione));


grazie mille veramente :love:







Teoria

Le transazioni servono ad eseguire in un database diverse query in modo simultaneo.
Questa esigenza nasce per poter prevenire e gestire facilmente le operazioni di ripristino dei dati nel caso un ipotetica procedura di aggiornamento fallisca prima del suo completamento, comportando così l'archiviazione di dati incoerenti nelle nostre tabelle.

Esempio pratico del problema

Ti pongo un esempio pratico per mostrarti la problematica, una procedura di acquisto in un possibile sito e-commerce.

Nel momento in cui un utente vuole acquistare il materiale riposto nel suo carrello, la nostra procedura deve svolgere queste operazioni:
  1. Selezionare il credito disponibile dell'utente
  2. Selezionare l'importo totale da pagare
  3. Eseguire lato codice i controlli necessari
  4. Segnare i prodotti come acquistati
  5. Aggiornare l'importo dell'utente

Se questo flusso, a causa di un errore, dovesse interrompersi tra il quarto e il quinto passaggio ci ritroveremmo che l'utente potrebbe trovarsi il materiale acquistato ma senza che gli sia stato detratto l'importo.
Questo problema si risolve grazie alle transazioni.

Come funziona una transazione

All'interno di una transazione le tue query vengono convalidate nel database unicamente quando richiami l'istruzione di commit.

Codice:
START TRANSACTION;
    -- Prepariamo le nostre operazioni
    SELECT ...
    UPDATE ....
    INSERT ....

-- tutto ok, convalidiamo le query
COMMIT;

La grande utilità di una transazione sta inoltre nel fatto che se dovesse intervenire un errore puoi annullare per intero tutte le query del blocco:

Codice:
START TRANSACTION;
    -- Prepariamo le nostre operazioni
    SELECT ...
    UPDATE ....
    INSERT ....

-- ho trovato un errore, non confermo le modifiche sul db
ROLLBACK;

E' chiaro che, finché non viene mandato il commit, se un altro utente richiede un dato da una tabella (magari quella su cui stiamo facendo un update) continuerà a leggere quello vecchio, anche se la transazione è già stata avviata.

Come fare quindi per impedire ad un utente di leggere un dato fino a che non finisco le operazioni sullo stesso ?

Lock delle righe

Il lock è uno strumento importante, senza di esso (tornando all'esempio dell'e-commerce) se un utente riuscisse ad avviare col giusto tempismo due transazioni differenti nello stesso momento, entrambe le transazioni useranno lo stesso importo dell'utente come riferimento per scalargli l'importo e l'ultima transazione eseguita gli sottrarrà quindi soltanto l'importo per i prodotti elaborati in quella transazione, lasciando che l'utente riceva degli "omaggi" non previsti dal sistema.

Mysql ci mette a disposizione la possibilità di realizzare un lock sulle righe lette tramite l'istruzione FOR UPDATE (quindi non sull'intera tabella).
Tale clausola fa si che gli altri processi che cercano di utilizzare il dato o i dati sotto lock saranno messi in attesa finché non concludiamo l'operazione.

Tornando al nostro esempio di procedura di acquisto:
Codice:
START TRANSACTION;
    -- Leggiamo l'importo utente
    SELECT importo FROM utenti WHERE utente = 'riferimento' FOR UPDATE;
    -- Facciamo le nostre operazioni di controllo
    ....
    -- Aggiorniamo l'importo utente
    UPDATE utenti SET importo = 'nuovo importo' WHERE utente = 'riferimento';

-- tutto ok, confermiamo l'esecuzione delle query sul database
COMMIT;


Mysqli

Il modulo mysqli di php mette a disposizione diverse istruzioni che permettono di gestire la transazione senza richiedere manualmente la query "start transaction".

Un esempio di transazione con queste istruzioni, sfruttando l'esempio di prima, potrebbe essere:
PHP:
// Iniziamo la nostra transazione
mysqli_autocommit($link, false);

$query = mysqli_query($link, "SELECT importo FROM utenti WHERE utente = 'riferimento' FOR UPDATE");

// se la query riesce, andiamo avanti
if ($query !== false) {

    // altre operazioni di controllo..

    // Scriviamo il dato
    if (mysqli_query($link, "UPDATE utenti SET importo = 'nuovo importo' WHERE utente = 'riferimento'") !== false) {
        
        // convalidiamo tutta la transazione
        mysqli_commit($link);

    } else {
        // errori nella query, rollback
        mysqli_rollback($link);
    }

} else {
    // se la query non riesce, diamo rollback delle operazioni
    mysqli_rollback($link);
}

// Riportiamo mysql al suo comportamento iniziale
mysqli_autocommit($link, true);


Il tuo caso specifico..

C'è da capire una cosa, la tua query di select ha come unica finalità quello di mostrare il dato nella pagina dell'utente ? Perché in questo caso non occorre mettere questa query sotto una transazione.

L'unico punto in cui devi adoperare una transazione è sulla modifica del dato e se vuoi gestire accessi contemporanei alla sua modifica dei impiegare il lock come ti ho illustrato.

Se nella tua pagina, cominci eseguendo la query di select (che userai anche per far visualizzare il dato) e successivamente controllando una variabile decidi se l'utente deve eseguire un update ti consiglio di ripetere la select nella transazione al fine di ottenere il lock ed effettuare in tranquillità l'update (oltre che a prendere sicuramente i dati più aggiornati nel caso si sia in attesa di un altra modifica sullo stesso).
 
Ultima modifica:

flameseeker

Utente Attivo
27 Nov 2013
699
0
0
ma in questo caso devo per forza inizializzare la transazione e finire con il commit perchè funzioni il blocco dei record selezionati?

Si, l'unica cosa è che prima di terminare il tuo script col die() (quando verifichi se le query ti ritornano errori) ti assicuri di richiamare la funzione mysqli_rollback() così da rilasciare il lock senza problemi.
 

Kelly

Utente Attivo
5 Set 2008
112
1
18
Supporto - consigli e chiarimenti per utilizzo transazioni ...

Perfetto...ora è proprio tutto chiaro...non so come ringraziarti....veramente...grossa mano !

:love::love:




Si, l'unica cosa è che prima di terminare il tuo script col die() (quando verifichi se le query ti ritornano errori) ti assicuri di richiamare la funzione mysqli_rollback() così da rilasciare il lock senza problemi.
 
Discussioni simili
Autore Titolo Forum Risposte Data
V Android Studio e proci con supporto VT-x Sviluppo app per Android 1
A Supporto per creazione pagina HTML HTML e CSS 8
S PHP Installazione da sorgente con supporto mysql (mariadb) PHP 0
K consiglio su supporto di memorizzazione MySQL 6
G Scelta device fisico di supporto sviluppo app per Android Sviluppo app per Android 2
P Supporto per creare uno script "Add Cart" Offerte e Richieste di Lavoro e/o Collaborazione 7
P Supporto per inserimento campo testo + tasto invio collegato ad un db PHP 1
F supporto slide Javascript 0
M Test supporto Video HTML5 ed formato MP4 HTML e CSS 1
M [Offro] Supporto per PHP, Javascript, Mysql Offerte e Richieste di Lavoro e/o Collaborazione 0
N EntertainmentWeb, cerco supporto! Presenta il tuo Sito 0
F Supporto e Hacking Console Presenta il tuo Sito 0
L facebook a supporto del sito creo pagina o gruppo? Discussioni Varie 0
najaru InvisionITA supporto italiano IPB Presenta il tuo Sito 0
S Fino a quanto durerá il supporto di Microsoft ad ASP? Classic ASP 3
N come inserire un supporto php per il web ? HTML e CSS 1
SolidSnake4 modulo supporto lingue php PHP 0
PoLe Supporto Utente [Fa morire dal ridere!] Discussioni Varie 3
M GDR ON-LINE: Cerco consulenza-aiuto-supporto-collaborazione Offerte e Richieste di Lavoro e/o Collaborazione 2
Apeweb Attivato Forum di supporto Presenta il tuo Sito 3
M Supporto photoshop... vi prego! Photoshop 4
peppoweb Supporto Php Hosting 5
G Consigli SEO per scrittura e struttura pagine SEO e Posizionamento 6
bubino8 Consigli e aiuti integrazione API Programmazione 3
G Access point con rete guest, consigli? Reti LAN e Wireless 0
G Richiesta consigli SEO: nuovo algoritmo Google (e altro) SEO e Posizionamento 2
P [Photoshop] Consigli per logo dimensioni minime Photoshop 1
B [WordPress] Consigli per sito b&b WordPress 1
Seeride Consigli per ripetitore wifi? Reti LAN e Wireless 2
T Consigli Impianto Videosorveglianza Esterna Deposito IP Cam e Videosorveglianza 8
D [PHP] Consigli su come creare form PHP 1
S Consigli per invio di comunicati stampa Discussioni Varie 2
G Consigli Logo aziendale Webdesign e Grafica 7
W [Javascript] Bootstrap Admin templates, mi dareste dei consigli? CMS (Content Management System) 0
E [Photoshop] consigli per stampa puzzle personalizzato Photoshop 0
N [Photoshop] Tavoletta Grafica XP-Pen O Wacom : Consigli per il primo Acquisto Photoshop 0
Zidane Spero di poter dare e ricevere molti consigli Presentati al Forum 0
I [HTML/CSS] Consigli sul mio primo sito HTML e CSS 9
G [WordPress] Consigli tema portfolio WordPress 3
G consigli per nuovo sito Hosting 2
B Consigli telecamera esterna IP Cam e Videosorveglianza 1
M Consigli prima di fare qualsiasi passo Domini 8
G mysql - problemi inserimento dati nel database, consigli. MySQL 3
braccobaldo Hosting per nuovo sito WordPress: consigli? Hosting 6
B Consigli per libro su Python Programmazione 1
voldemort Consigli per Cloud Object Storage Cloud Computing e Cloud Server 1
zorro Consigli.........cercasi PHP 2
A consigli sull'action dei form PHP 9
P Consigli per sistemare meglio il menu HTML e CSS 63
D Suggerimenti e/o consigli per App personale gestione Rapporto Interventi Tecnici (RIT Sviluppo app per Android 0

Discussioni simili