Yii2: вложенные транзакции
16 февраля 2014
Qiang добавил поддержку вложенных транзакций через savepoint-ы:
// верхняя транзакция $transaction1 = $connection->beginTransaction(); try { $connection->createCommand($sql1)->execute(); // внутренняя транзакция $transaction2 = $connection->beginTransaction(); try { $connection->createCommand($sql2)->execute(); $transaction2->commit(); } catch (Exception $e) { $transaction2->rollBack(); } $transaction1->commit(); } catch (Exception $e) { $transaction1->rollBack(); }
Комментарии RSS по email OK
А разве старт новой транзакции автоматически не фиксирует предыдущую транзакцию? Из документации: "Transactions cannot be nested. This is a consequence of the implicit commit performed for any current transaction when you issue a START TRANSACTION statement or one of its synonyms." Или расскажите пожалуйста подробней какая магия у вас там происходит?
2NickSun есть вложенные транзакции (SAVEPOINT) но они зло )) в одном проекте прикинул что это будет просто круто, и панацея чуть ли не от всего, но из-за сложности проекта, точек в которых создавались сейвпоинты было дофига, контролировать в какой конкртнеый момент что из них и где будет создваться, оказалось катастрофически трудно... заниматься отладкой на упавших сейвпоинтах вообще мрак. В итоге отказался, вырезал под нож вложенные транзакции, и просто сделал нормальную предсказуемую обработку исключений )).
Sam, а что, прям для всех движков БД поддерживаемых это сделали?
А мне понравилось то, что в AR появился метод 'transactions'.
Кстати, получается, если в transactions одной модели, а потом еще тоже самое есть в другой, там автоматом будут юзаться SAVEPOINT's?
lexand, SAVEPOINT - это не вложенные транзакции. Они работают в пределах одной (!) текущей транзакции. Это всего лишь способ сделать откат части транзакции при определенных условиях.
Уж если и используются SAVEPOINT-ы, то лучше сделать методы Connection::setSavepoint(), Connection::rollbackSavepoint() и Connection::releaseSavepoint(). Так хоть не будет каши в голове с подменой понятий.
NickSun, так судя по определкнию этот механизм и делает возможность "вложенных транзакций". Логично же?
На базах, которые позволяют сделать честные вложенные транзакции, savepoint-ы не используются.
И все таки помогите разобраться - чем честные вложенные отличаются от точек сохранения. есть чтото принципиальное или просто одну и туже хрень назвали двумя разными терминами???
См. MSSQL и Sybase.
не знаю прям что и сказать судя по описаниям - одно и тоже,
просто представьте что SAVEPOINT в PostgreSQL/MySQL заменили на BEGIN TRANSACTION...
единственно что приходит на ум, если говорить о принципиальной разнице, это уровни изоляции транзакций, тогда конечно честные транзакции отличались бы от точек сохранения. Но.... я просто не представляю нафига вложенным траназкиям если они действительно прям такие честные - разные уровни изоляции, не могу придумать случая использования даже.
Пока autocommit = 1 у меня транзакции не работают Если напрямую в БД выполняю запрос и меняю SET autocommit = 0 то все работает, если из кода менять autocommit то транзакции не работают
С чем это может быть связанно? Таблицы InnoDB
С тем, что сама база вложенные транзакции не поддерживает и они эмулируются через savepoint.
Я отслеживал уровень вложенности, он там = 0 и сам yii2 не работает с SAVEPOINT-ами (не доходит до этого), специально отслеживал уровень вложенности.
Пробовал менять autocommit следующий образом: \Yii::$app->getDb()->pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, 0); и \Yii::$app->db->createCommand('SET autocommit = 0')->execute();
Далее кидаю запрос: SELECT @@autocommit FROM dual Получаю autocommit = 0
Но работает как будто =1 Если на прямую в БД выполняю запрос 'SET autocommit = 0' то транзакции нормально работают.
Внутри транзакции я создаю таблицы, добавляю поля и внешние ключи и прочие подобные операции и мне нужно чтобы когда на каком-то этапе происходит сбой все действия откатывались
А, ну так MySQL не умеет в транзакциях менять схему. Как только есть изменение схемы, происходит автокоммит.
Не знал, спасибо :) А как быть с autocmmit, почему он из кода не хочет меняться? Точнее меняется но при этом эффекта никакого
Про autocommit не знаю...
Спасибо за помощь