Откат транзакции не работает - PullRequest
5 голосов
/ 17 февраля 2010

Я сделал оболочку базы данных с дополнительными функциями для системы PDO (да, я знаю оболочку для оболочки, но это просто PDO с некоторыми дополнительными функциями). Но я заметил проблему.

Не работает следующим образом:

<?php
var_dump($db->beginTransaction());

$db->query('
 INSERT INTO test
 (data) VALUES (?)
 ;',
 array(
  'Foo'
 )
);
print_r($db->query('
 SELECT *
 FROM test
 ;'
)->fetchAll());

var_dump($db->rollBack());

print_r($db->query('
 SELECT *
 FROM test
 ;'
)->fetchAll());
?>

var_dump показывает, что функции beginTransaction и rollBack возвращают true, поэтому ошибок нет.

Я ожидал, что первый вызов print_r покажет массив из N элементов, а второй вызов покажет N-1 элементов. Но это неправда, они оба показывают одинаковое количество предметов.

Мой запрос $ db-> (, ) не вызывает ничего, кроме $ pdo-> prepare () -> execute () (с дополнительной обработкой ошибок, конечно).

Так что я думаю, что или транзакционная система MySQL не работает, или возможности PDO не работают, или я вижу что-то не так.

Кто-нибудь знает, в чем проблема?

Ответы [ 5 ]

14 голосов
/ 17 февраля 2010

Проверьте, равен ли ваш тип базы данных innoDB. Одним словом вы должны проверить, поддерживает ли ваша база данных транзакции.

4 голосов
/ 17 февраля 2010

Две возможные проблемы:

  1. Таблица MyISAM, которая не поддерживает транзакции. Используйте InnoDB.

  2. Убедитесь, что автоматическая фиксация выключена.

http://www.php.net/manual/en/pdo.transactions.php

3 голосов
/ 17 февраля 2010

Я ввожу это как ответ, так как комментарий слишком мал, чтобы содержать следующее:

PDO - это просто оболочка для различных библиотек интерфейса базы данных более низкого уровня. Если библиотека низкого уровня не будет жаловаться, то будет либо PDO. Поскольку MySQL поддерживает транзакции, никакие транзакции не будут возвращать синтаксическую ошибку или что-либо еще. Вы можете использовать таблицы MyISAM в транзакциях, но любые операции над ними будут выполняться так, как если бы автоматическая фиксация все еще была активна:

mysql> create table myisamtable (x int) engine=myisam;
Query OK, 0 rows affected (0.00 sec)

mysql> create table innodbtable (x int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into myisamtable (x) values (1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into innodbtable (x) values (2);
Query OK, 1 row affected (0.00 sec)

mysql> rollback;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select * from myisamtable;
+------+
| x    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

mysql> select * from innodbtable;
Empty set (0.00 sec)

mysql>

Как видите, несмотря на то, что транзакция была активной и некоторые действия были выполнены с таблицей MyISAM, ошибок не было.

2 голосов
/ 17 февраля 2010

MySQL не поддерживает транзакции для типа таблицы MyISAM, который, к сожалению, является типом таблицы по умолчанию.

Если вам нужны транзакции, вам следует переключиться на тип таблицы InnoDB.

0 голосов
/ 04 февраля 2019

Другая причина, по которой это может произойти, заключается в том, что определенные типы операторов SQL вызывают немедленную автоматическую фиксацию. У меня был большой скрипт, который выполнялся в транзакции, которая была зафиксирована немедленно и игнорировала транзакцию. В конце концов я обнаружил, что это потому, что любой оператор ALTER TABLE немедленно вызывает коммит.

Типы операторов, вызывающих автоматическую фиксацию:

  • Все, что изменяет таблицу или базу данных, например ALTER TABLE, CREATE TABLE и т. Д.
  • Все, что изменяет права доступа к таблице, например ALTER USER или SET PASSWORD
  • Все, что блокирует эти таблицы или запускает новую транзакцию
  • операторы загрузки данных
  • Административные заявления, такие как ANALYZE TABLE, FLUSH или CACHE INDEX
  • Операторы управления репликацией, например, все, что связано с ведомым устройством или ведущим

Более подробную информацию и полный список можно найти здесь: https://dev.mysql.com/doc/refman/8.0/en/implicit-commit.html

Если у вас возникла эта проблема только с определенным сценарием, и вы уверены, что используете InnoDB, возможно, вы захотите посмотреть, соответствуют ли какие-либо операторы SQL в вашем сценарии этим

...