Nie, transakcja nie jest śledzona w przypadku niepowodzenia pojedynczej instrukcji SQL.
Jeśli pojedyncza instrukcja SQL nie powiedzie się, instrukcja jest cofany (jak opisano w odpowiedzi @eggyal) - ale transakcja jest nadal otwarty. Jeśli zadzwonisz commit
teraz nie ma wycofywania pomyślnych instrukcji i po prostu wstawiłeś "uszkodzone" dane do swojej bazy danych. Możesz to łatwo odtworzyć:
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)
Widzisz, że wstawienie 'foo' i 'bar' powiodło się, chociaż druga instrukcja SQL nie powiodła się - możesz nawet zobaczyć, że AUTO_INCREMENT
-wartość została zwiększona przez błędne zapytanie.
Musisz więc sprawdzić wyniki każdego query
- wywołaj, a jeśli się nie powiedzie, wywołaj rollback
aby cofnąć inne udane zapytania. Więc kod Lorenzo w podręczniku PHP ma sens.
Jedynym błędem, który zmusza MySQL do wycofania transakcji, jest „zakleszczenie transakcji” (jest to specyficzne dla InnoDB, inne silniki pamięci masowej mogą inaczej obsługiwać te błędy).