rollback
MySQLi è un'estensione PHP per interagire con i database MySQL. La funzione rollback annulla le modifiche di una transazione non ancora confermata.
Introduzione
MySQLi è l'estensione PHP utilizzata per comunicare con i database MySQL. La funzione mysqli_rollback() (o il metodo $mysqli->rollback() in stile orientato agli oggetti) annulla tutte le modifiche effettuate dall'inizio di una transazione. Questa pagina spiega quando e perché è necessaria, come si integra con mysqli_commit() e mostra esempi eseguibili in entrambi gli stili, procedurale e orientato agli oggetti.
Se non conosci ancora l'estensione, inizia con PHP MySQLi e la connessione a MySQL.
Cos'è la funzione MySQLi Rollback?
Una transazione è un gruppo di operazioni sul database trattate come un'unica unità di lavoro: o vengono applicate tutte, o nessuna. mysqli_rollback() rende possibile il "nessuna" — scarta tutte le modifiche effettuate dall'inizio della transazione e riporta il database allo stato precedente.
L'esempio classico è un trasferimento di denaro. Sottrarre da un conto e aggiungere all'altro devono avvenire entrambi; se la seconda query fallisce, non si può lasciare applicata la prima. Il rollback garantisce che i conti restino bilanciati.
bool mysqli_rollback(mysqli $mysql, int $flags = 0, ?string $name = null)Restituisce true in caso di successo e false in caso di fallimento. Il parametro opzionale $name consente di tornare a un savepoint con nome invece che all'intera transazione.
Autocommit: perché servono le transazioni
Per impostazione predefinita MySQL opera in modalità autocommit, il che significa che ogni singola istruzione viene confermata immediatamente e in modo permanente — non c'è nulla da annullare. Chiamare mysqli_begin_transaction() disattiva l'autocommit per la durata della transazione, in modo che le modifiche rimangano in sospeso finché non si esegue esplicitamente commit() o rollback(). Consulta autocommit per il comportamento completo.
Come funziona il flusso di rollback
Una transazione completa segue quattro passaggi:
- Connetti al server.
- Avvia una transazione con
mysqli_begin_transaction(). - Esegui le query.
- Conferma se tutto è andato a buon fine, oppure annulla se qualcosa è fallito.
Ecco un esempio procedurale completo:
<?php
// Create a connection to the MySQL server
$conn = mysqli_connect("localhost", "username", "password", "database");
// Check connection
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}
// Start a transaction
mysqli_begin_transaction($conn);
// Execute queries and make changes to the database
$insert = mysqli_query($conn, "INSERT INTO `my_table` (column1, column2) VALUES ('value1', 'value2')");
$update = mysqli_query($conn, "UPDATE `my_table` SET column1 = 'new_value' WHERE id = 1");
// Check if queries succeeded
if ($insert && $update) {
// Commit the transaction if all queries succeed
mysqli_commit($conn);
echo "Transaction committed successfully.";
} else {
// Rollback the changes if any query fails
mysqli_rollback($conn);
echo "Transaction failed and rolled back: " . mysqli_error($conn);
}
mysqli_close($conn);
?>Viene avviata una transazione, vengono eseguite due query e il risultato determina l'esito: commit in caso di successo, rollback in caso di fallimento. Nota che mysqli_query() restituisce false solo quando una query fallisce a livello SQL — non genera eccezioni, quindi è necessario controllare il valore restituito a meno che non si abilitino le eccezioni (mostrato di seguito).
Stile orientato agli oggetti con prepared statement
La maggior parte del codice in produzione utilizza l'API orientata agli oggetti insieme ai prepared statement, che prevengono l'SQL injection separando la query dai suoi dati. Attivare la modalità di segnalazione delle eccezioni consente di racchiudere l'intera transazione in un singolo blocco try/catch ed eseguire il rollback da un unico punto:
<?php
// Throw exceptions on any MySQLi error instead of returning false
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "username", "password", "database");
$mysqli->begin_transaction();
try {
$stmt = $mysqli->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt->bind_param("di", $amount, $fromId);
$amount = 100.00;
$fromId = 1;
$stmt->execute();
$stmt = $mysqli->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt->bind_param("di", $amount, $toId);
$toId = 2;
$stmt->execute();
// Both updates succeeded — make them permanent
$mysqli->commit();
echo "Transfer committed.";
} catch (mysqli_sql_exception $e) {
// Anything threw — undo everything
$mysqli->rollback();
echo "Transfer failed and rolled back: " . $e->getMessage();
}
$mysqli->close();
?>Poiché MYSQLI_REPORT_STRICT fa sì che le istruzioni fallite lancino mysqli_sql_exception, non è necessario verificare il valore restituito da ogni query — il blocco catch gestisce tutti i percorsi di errore. Consulta le eccezioni PHP per ulteriori informazioni su try/catch.
Rollback a un savepoint
Un savepoint è un marcatore con nome all'interno di una transazione. Eseguire il rollback fino a esso annulla solo il lavoro svolto dopo il savepoint, lasciando in sospeso le modifiche precedenti. Ciò è utile quando una parte della transazione è opzionale:
<?php
$mysqli->begin_transaction();
$mysqli->query("INSERT INTO orders (customer_id) VALUES (5)");
$mysqli->savepoint("after_order");
$mysqli->query("INSERT INTO order_items (order_id, sku) VALUES (LAST_INSERT_ID(), 'BAD')");
// Undo only the order_items insert; the order row remains pending
$mysqli->rollback(0, "after_order");
$mysqli->commit(); // commits the order without the bad item
?>Casi d'uso della funzione MySQLi Rollback
La funzione MySQLi Rollback è utile in diversi scenari, tra cui:
1. Integrità dei dati
Mantiene la coerenza del database ripristinando gli aggiornamenti parziali quando un'operazione fallisce, garantendo che i record rimangano validi.
2. Gestione degli errori
Fornisce un meccanismo di recupero pulito. Quando si verifica un errore, il rollback impedisce la creazione di dati orfani o corrotti, consentendo all'applicazione di registrare e visualizzare messaggi di errore significativi.
3. Gestione delle transazioni
Semplifica il controllo del flusso di lavoro consentendo agli sviluppatori di interrompere una sequenza di operazioni dipendenti e ricominciare o abbandonare in modo sicuro la transazione senza pulizia manuale.
Vantaggi della funzione MySQLi Rollback
La funzione MySQLi Rollback offre diversi vantaggi tecnici per gli sviluppatori PHP:
1. Atomicità
Garantisce che un gruppo di operazioni sul database abbia successo o fallisca interamente, prevenendo aggiornamenti parziali che potrebbero corrompere i dati.
2. Debug semplificato
Quando una transazione fallisce, il rollback ripristina il database allo stato precedente, rendendo più facile isolare e correggere la query problematica senza pulizia manuale.
3. Ottimizzazione delle prestazioni
Raggruppare più query in una singola transazione riduce l'overhead di confermare le modifiche singolarmente, portando a operazioni sul database più veloci.
Insidie comuni
- Il motore di archiviazione è importante. Solo i motori transazionali supportano il rollback. Il motore predefinito di MySQL InnoDB lo supporta; il vecchio motore MyISAM ignora silenziosamente le transazioni, quindi un rollback lì non cambia nulla. Assicurati che le tue tabelle siano InnoDB.
- Le istruzioni DDL eseguono l'autocommit. Istruzioni come
CREATE TABLE,ALTER TABLEeDROP TABLEconfermano implicitamente la transazione corrente in MySQL — non è possibile annullarle con un rollback. Mantieni le modifiche allo schema fuori dalle transazioni che intendi annullare. - Esegui il rollback esattamente una volta. Dopo un
commit()o unrollback()completo la transazione è terminata. Avvia una nuova transazione prima di eseguire ulteriore lavoro transazionale. - La disconnessione esegue il rollback automatico. Se la connessione viene persa durante una transazione, MySQL esegue automaticamente il rollback — il lavoro non confermato non viene mai lasciato applicato parzialmente.
Conclusione
La funzione mysqli_rollback() è essenziale per gli sviluppatori PHP che hanno bisogno di annullare le modifiche al database durante una transazione. Garantisce l'integrità dei dati, semplifica la gestione delle transazioni e migliora la gestione degli errori. Seguendo i passaggi di questa guida, gli sviluppatori possono implementare in modo sicuro i rollback per mantenere operazioni affidabili sul database.