PHP-транзакция MySQL между базами данных

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

Я использую тот же объект подключения (mysqli) и выполняю транзакции следующим образом:

$mysqli->autocommit(false);

try {

    // Assume here that some code would throw an exception

    $stmt = $mysqli->prepare("INSERT INTO db1.x (column) VALUES (y)");
    $stmt->execute();
    $stmt->close();

    $stmt = $mysqli->prepare("INSERT INTO db2.x (column) VALUES (y)");
    $stmt->execute();
    $stmt->close();

    $mysqli->commit();
    // Great success

} catch (Exception $e) {

    $mysqli->rollback();
    throw $e; // handle elsewhere

}

Разрешено ли это, и будет ли он правильно фиксировать и откатываться? Согласно руководству (http://dev.mysql.com/doc/refman/5.6/en/xa.html) и другие потоки на SO, кажется, мне нужно использовать операторы XA, но не совсем ясно (мне), если это при использовании нескольких серверов баз данных, нескольких подключений или просто в целом при выполнении кода выше.


person nickdnk    schedule 24.02.2016    source источник
comment
Я бы предположил, что если они находятся на одном хост-компьютере БД, это сработает.   -  person Ray    schedule 25.02.2016
comment
Ну, если бы это было не так, я бы не смог использовать один и тот же объект mysqli для обоих операторов.   -  person nickdnk    schedule 25.02.2016
comment
да, в данном конкретном случае сработает. транзакции выполняются для каждого соединения. если вы держите открытыми два соединения и запускаете транзакцию в каждом, то у вас есть две совершенно отдельные/разные транзакции, и действия на одном не повлияют на другое.   -  person Marc B    schedule 25.02.2016
comment
@MarcB - я знаю об этом, и поэтому в вопросе конкретно указано, что я использую тот же объект соединения. Если вы уверены и можете подтвердить свою претензию, не стесняйтесь опубликовать ответ :)   -  person nickdnk    schedule 25.02.2016
comment
Кажется, что этот пример уже содержит почти все, что вам нужно для его проверки.   -  person Don't Panic    schedule 25.02.2016
comment
@Don'tPanic Ха-ха - да, но я не уверен на 100%, что кажется, что работа всегда равна тому, что вы должны делать это так, и именно так это и должно быть сделано :)   -  person nickdnk    schedule 25.02.2016


Ответы (2)


В соответствии с запросом комментария выше, опуская отзыв о создании/использовании:

mysql> create database x;
mysql> use x;
mysql> create table x (x int);
mysql> create database y;
mysql> use y;
mysql> create table y (y int);
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

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

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

mysql> rollback;
Query OK, 0 rows affected (0.01 sec)

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

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

Обратите внимание, что все это в одном соединении с одним экземпляром mysql. Это НЕ будет работать, если базы данных размещены на разных серверах, или вы выполняете каждое создание/вставку на разных соединениях.

person Marc B    schedule 24.02.2016
comment
Я думаю, что я возьму ваши слова и этот пример для него. Спасибо :) - person nickdnk; 25.02.2016

Транзакции применяются к серверу в целом. Базы данных просто используются для группировки таблиц с целью предоставления разрешений (например, вы можете предоставить разрешения для database.*) и предоставления некоторых значений по умолчанию при создании новых таблиц. И они используются, чтобы позволить вам выбрать базу данных по умолчанию с помощью оператора USE, поэтому вам не нужно указывать имена баз данных в каждом запросе.

person Barmar    schedule 24.02.2016