Подтвердить что ты не робот

Операции Mysql в транзакциях

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

Я хочу быть уверенным - это транзакции в транзакциях, действительные в mysql? Если да, есть ли способ узнать, сколько уровней вы находитесь во вложенных транзакциях? (т.е. сколько откатов потребуется, чтобы вернуться к норме)

Спасибо заранее, Brian

4b9b3361

Ответ 1

Эта страница руководства может вас заинтересовать: 12.3.3. Заявления, которые вызывают неявное обязательство; цитируя несколько предложений:

Операции, перечисленные в этом разделе (и любые синонимы для них) неявно завершите транзакцию, как если бы вы сделали a COMMIT перед выполнением утверждение.


И немного дальше на странице:

Управление транзакциями и блокировка заявления. BEGIN, LOCK TABLES, SET autocommit = 1 (если значение равно не уже 1), START TRANSACTION, UNLOCK TABLES.


См. Также этот параграф:

Транзакции не могут быть вложенными.
Это следствие неявного COMMITвыполняется для любой текущей транзакции при выпуске START TRANSACTIONили один из его синонимов.


Надеюсь, это поможет!

Ответ 2

В отличие от всех остальных, вы можете эффективно создавать транзакции в транзакциях, и это очень просто. Вы просто создаете местоположения SAVEPOINT и используете ROLLBACK TO savepoint для отката части транзакции, где точка сохранения - это то, что вы даете точке сохранения. Ссылка на документацию MySQL: http://dev.mysql.com/doc/refman/5.0/en/savepoint.html И, конечно же, ни один из запросов в любой транзакции не должен иметь тип, который неявно совершает, или вся транзакция будет совершена.

Примеры:

START TRANSACTION;

# queries that don't implicitly commit

SAVEPOINT savepoint1;

# queries that don't implicitly commit

# now you can either ROLLBACK TO savepoint1, or just ROLLBACK to reverse the entire transaction.

SAVEPOINT savepoint2;

# queries that don't implicitly commit

# now you can ROLLBACK TO savepoint1 OR savepoint2, or ROLLBACK all the way.
# e.g.

ROLLBACK TO savepoint1;
COMMIT; # results in committing only the part of the transaction up to savepoint1

В PHP я написал такой код, и он отлично работает:

foreach($some_data as $key => $sub_array) {
  $result = mysql_query('START TRANSACTION'); // note mysql_query is deprecated in favor of PDO
  $rollback_all = false; // set to true to undo whole transaction
  for($i=0;$i<sizeof($sub_array);$i++) {
    if($sub_array['set_save'] === true) {
      $savepoint = 'savepoint' . $i;
      $result = mysql_query("SAVEPOINT $savepoint");
    }
    $sql = 'UPDATE `my_table` SET `x` = `y` WHERE `z` < `n`'; // some query/queries
    $result = mysql_query($sql); // run the update query/queries

    $more_sql = 'SELECT `x` FROM `my_table`'; // get data for checking
    $result = mysql_query($more_sql);

    $rollback_to_save = false; // set to true to undo to last savepoint
    while($row = mysql_fetch_array($result)) {
      // run some checks on the data
      // if some check says to go back to savepoint:
      $rollback_to_save = true; // or just do the rollback here.
      // if some check says to rollback entire transaction:
      $rollback_all = true;
    }
    if($rollback_all === true) {
      mysql_query('ROLLBACK'); // rollback entire transaction
      break; // break out of for loop, into next foreach
    }
    if($rollback_to_save = true) {
      mysql_query("ROLLBACK TO $savepoint"); // undo just this part of for loop
    }
  } // end of for loop
  mysql_query('COMMIT'); // if you don't do this, the whole transaction will rollback
}

Ответ 3

Я хочу быть уверенным - это транзакции внутри транзакций, действительных в mysql?

Нет.

Ответ 4

MySql не поддерживает вложенные транзакции. Есть несколько способов, которыми вы можете его эмулировать. Во-первых, вы можете использовать точки сохранения как форму транзакции, так что вы получаете два уровня транзакций; Я использовал это для тестирования, но я не уверен в ограничениях, если вы используете его в производственном коде. Более простым решением является игнорировать второй begin transaction и вместо этого увеличивать счетчик. Для каждого commit вы уменьшаете его. Как только вы достигнете нуля, вы сделаете фактический commit. Есть очевидные ограничения этого; Например. откат откатит все транзакции, но для случая, когда вы используете транзакции для обработки ошибок, это может быть приемлемым.

Ответ 5

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

Из документов MySQL по транзакциям XA:

MySQL 5.0.3 и выше поддерживают серверную поддержку транзакций XA. В настоящее время эта поддержка доступна для механизма хранения InnoDB. Реализация MySQL XA основана на документе X/Open CAE. Обработка распределенных транзакций: спецификация XA. Этот документ публикуется The Open Group и доступен по адресу http://www.opengroup.org/public/pubs/catalog/c193.htm. Ограничения текущей реализации XA описаны в разделе E.5 "Ограничения на транзакции XA".

Пример транзакции XA для вас:

# Start a new XA transaction
XA START;

    # update my bank account balance, they will never know!
    UPDATE `bank_accounts` SET `balance` = 100000 WHERE `id` = 'mine';

    # $100,000.00 is a bit low, I'm going to consider adding more, but I'm not sure so 
    # I will start a NESTED transaction and debate it...
    XA START;

        # max int money! woo hoo!
        UPDATE `bank_accounts` SET `balance` = 2147483647 WHERE `id` = 'mine';

    # maybe thats too conspicuous, better roll back
    XA ROLLBACK;


# The $100,000 UPDATE still applies here, but the max int money does not, going for it!
XA COMMIT;

# Oh No!  Sirens!  It the popo's!!! run!!
# What the hell are they using ints for money columns anyway!  Ahhhh!

Документация MySQL для транзакций XA:

я < 3 XA Сделки 4 Eva!

Ответ 6

Возможно, вы захотите проверить свою тестовую метадологию. Вне MaxDB MySQL не поддерживает ничего удаленного, как вложенные транзакции.