<rmcreative>

RSS

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

  1. №8818
    NickSun
    NickSun 16.02.2014, 23:06:44

    А разве старт новой транзакции автоматически не фиксирует предыдущую транзакцию? Из документации: "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." Или расскажите пожалуйста подробней какая магия у вас там происходит?

  2. №8819
    lexand
    lexand 17.02.2014, 1:20:40

    2NickSun есть вложенные транзакции (SAVEPOINT) но они зло )) в одном проекте прикинул что это будет просто круто, и панацея чуть ли не от всего, но из-за сложности проекта, точек в которых создавались сейвпоинты было дофига, контролировать в какой конкртнеый момент что из них и где будет создваться, оказалось катастрофически трудно... заниматься отладкой на упавших сейвпоинтах вообще мрак. В итоге отказался, вырезал под нож вложенные транзакции, и просто сделал нормальную предсказуемую обработку исключений )).

  3. №8820
    Алексей
    Алексей 17.02.2014, 21:37:30

    Sam, а что, прям для всех движков БД поддерживаемых это сделали?

    А мне понравилось то, что в AR появился метод 'transactions'.

    Кстати, получается, если в transactions одной модели, а потом еще тоже самое есть в другой, там автоматом будут юзаться SAVEPOINT's?

  4. №8822
    NickSun
    NickSun 17.02.2014, 22:04:34

    lexand, SAVEPOINT - это не вложенные транзакции. Они работают в пределах одной (!) текущей транзакции. Это всего лишь способ сделать откат части транзакции при определенных условиях.

  5. №8823
    NickSun
    NickSun 17.02.2014, 22:10:47

    Уж если и используются SAVEPOINT-ы, то лучше сделать методы Connection::setSavepoint(), Connection::rollbackSavepoint() и Connection::releaseSavepoint(). Так хоть не будет каши в голове с подменой понятий.

  6. №8824
    lexand
    lexand 17.02.2014, 22:42:07

    NickSun, так судя по определкнию этот механизм и делает возможность "вложенных транзакций". Логично же?

  7. №8825
    Sam
    Sam 17.02.2014, 23:07:15

    На базах, которые позволяют сделать честные вложенные транзакции, savepoint-ы не используются.

  8. №8826
    lexand
    lexand 18.02.2014, 0:05:49

    И все таки помогите разобраться - чем честные вложенные отличаются от точек сохранения. есть чтото принципиальное или просто одну и туже хрень назвали двумя разными терминами???

  9. №8827
    Sam
    Sam 18.02.2014, 0:28:08

    См. MSSQL и Sybase.

  10. №8828
    lexand
    lexand 18.02.2014, 1:32:56

    не знаю прям что и сказать судя по описаниям - одно и тоже,

    просто представьте что SAVEPOINT в PostgreSQL/MySQL заменили на BEGIN TRANSACTION...

    единственно что приходит на ум, если говорить о принципиальной разнице, это уровни изоляции транзакций, тогда конечно честные транзакции отличались бы от точек сохранения. Но.... я просто не представляю нафига вложенным траназкиям если они действительно прям такие честные - разные уровни изоляции, не могу придумать случая использования даже.

  11. №9858
    Александр
    Александр 01.07.2015, 18:03:20

    Пока autocommit = 1 у меня транзакции не работают Если напрямую в БД выполняю запрос и меняю SET autocommit = 0 то все работает, если из кода менять autocommit то транзакции не работают

    С чем это может быть связанно? Таблицы InnoDB

  12. №9859
    Sam
    Sam 02.07.2015, 9:56:19

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

  13. №9863
    Александр
    Александр 02.07.2015, 18:32:42

    Я отслеживал уровень вложенности, он там = 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' то транзакции нормально работают.


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

  14. №9865
    Sam
    Sam 03.07.2015, 10:28:59

    А, ну так MySQL не умеет в транзакциях менять схему. Как только есть изменение схемы, происходит автокоммит.

  15. №9867
    Александр
    Александр 03.07.2015, 10:42:20

    Не знал, спасибо :) А как быть с autocmmit, почему он из кода не хочет меняться? Точнее меняется но при этом эффекта никакого

  16. №9871
    Sam
    Sam 04.07.2015, 0:04:39

    Про autocommit не знаю...

  17. №9873
    Александр
    Александр 04.07.2015, 0:55:32

    Спасибо за помощь

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.