Не, транзакцията не следи, ако единичен SQL израз е неуспешен.
Ако единичен SQL-изявление е неуспешен изявление се връща обратно (както е описано в отговора на @eggyal) - но транзакцията все още е отворен. Ако извикате commit
сега няма връщане назад на успешните изрази и вие просто сте вмъкнали "повредени" данни във вашата база данни. Можете лесно да възпроизведете това:
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)
Виждате, че вмъкването на „foo“ и „bar“ е успешно, въпреки че вторият SQL израз е неуспешен – можете дори да видите, че AUTO_INCREMENT
-стойността е увеличена от грешната заявка.
Така че трябва да проверявате резултатите от всяка query
-извикване и ако едно не успее, извикване на rollback
за да отмените иначе успешните заявки. Така че кодът на Лоренцо в ръководството за PHP има смисъл.
Единствената грешка, която принуждава MySQL да върне обратно транзакцията, е „блокировка на транзакция“ (и това е специфично за InnoDB, други машини за съхранение може да обработват тези грешки по различен начин).