Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como funciona o mysqli::commit &mysqli::rollback?


Não, a transação não acompanha se uma única instrução SQL falhar.

Se uma única instrução SQL falhar na instrução é revertida (como descrito na resposta de @eggyal) - mas a transação ainda está aberto. Se você chamar commit agora, não há rollback das declarações bem-sucedidas e você acabou de inserir dados "corrompidos" em seu banco de dados. Você pode reproduzir isso 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)

Você vê que a inserção de 'foo' e 'bar' foi bem-sucedida, embora a segunda instrução SQL tenha falhado - você pode até ver que o AUTO_INCREMENT -valor foi aumentado pela consulta defeituosa.

Então você tem que verificar os resultados de cada query -call e se um falhar, chame rollback para desfazer as consultas bem-sucedidas. Portanto, o código de Lorenzo no manual do PHP faz sentido.

O único erro que força o MySQL a reverter a transação é um "impasse de transação" (e isso é específico do InnoDB, outros mecanismos de armazenamento podem lidar com esses erros de maneira diferente).