Mysql
 sql >> Database >  >> RDS >> Mysql

Come funzionano mysqli::commit e mysqli::rollback?

No, la transazione non tiene traccia se una singola istruzione SQL non riesce.

Se una singola istruzione SQL non riesce, l'istruzione viene eseguito il rollback (come descritto nella risposta di @eggyal), ma la transazione è ancora aperto. Se chiami commit ora, non c'è alcun rollback delle istruzioni riuscite e hai appena inserito dati "corrotti" nel tuo database. Puoi riprodurlo facilmente:

m> CREATE TABLE transtest (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
 name VARCHAR(100) NOT NULL DEFAULT '',
 CONSTRAINT UNIQUE KEY `uq_transtest_name` (name)) ENGINE=InnoDB;
Query OK, 0 rows affected (0.07 sec)

m> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

m> INSERT INTO transtest (name) VALUE ('foo');
Query OK, 1 row affected (0.00 sec)

m> INSERT INTO transtest (name) VALUE ('foo');
ERROR 1062 (23000): Duplicate entry 'foo' for key 'uq_transtest_name'

m> INSERT INTO transtest (name) VALUE ('bar');
Query OK, 1 row affected (0.00 sec)

m> COMMIT;
Query OK, 0 rows affected (0.02 sec)

m> SELECT * FROM transtest;
+----+------+
| id | name |
+----+------+
|  3 | bar  |
|  1 | foo  |
+----+------+
2 rows in set (0.00 sec)

Vedi che l'inserimento di 'foo' e 'bar' ha avuto successo anche se la seconda istruzione SQL non è riuscita - puoi anche vedere che AUTO_INCREMENT -value è stato aumentato dalla query errata.

Quindi devi controllare i risultati di ogni query -call e se uno fallisce, chiama rollback per annullare le query altrimenti riuscite. Quindi il codice di Lorenzo nel manuale PHP ha senso.

L'unico errore che costringe MySQL a ripristinare la transazione è un "deadlock della transazione" (e questo è specifico di InnoDB, altri motori di archiviazione potrebbero gestire questi errori in modo diverso).