MySQL InnoDB - запутался в транзакциях - PullRequest
2 голосов
/ 27 января 2011

Я использую MySQL уже много лет, но у меня нет большого опыта использования движка InnoDB.

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

Тогда мой вопрос - почему, в приведенном ниже коде .... все еще вводит первые два запроса в базу данных, когда явно существует проблема с третьим запросом?

$query = "BEGIN";
mysql_query($query);

$query = "INSERT INTO list_columns(lid,column_name) VALUES(8,'test')";
mysql_query($query);

$query = "INSERT INTO list_columns(lid,column_name) VALUES(8,'test')";
mysql_query($query);

$query = "INSERT INT list_columns(lid,column_name) VALUES(8,'test')";
mysql_query($query);

$query = "COMMIT";
mysql_query($query);

Редактировать: Я понимаю об использовании ROLLBACK & all ..... но я думал, что вся цель транзакций заключается в том, что если вообще возникнут какие-либо проблемы с каким-либо из запросов в транзакции, тогда ни один из них не будет выполнен ... или это только в случае с несколькими вставками в одинзапрос например .... если одна из вставок представляет проблему, то ни одна не будет вставлена?

Ответы [ 4 ]

10 голосов
/ 27 января 2011

Если проблема что-то вроде « Эта вставка нарушила уникальный ключ », то будет выполнена фиксация. Вы должны проверить, вернули ли запрос ошибки, и если да, то ROLLBACK.

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

Конечно, поскольку ваши 3 запроса здесь одинаковы, это глупый пример. По крайней мере, измените lid, чтобы увидеть. Почему бы тебе не сделать быстрый тест?

Редактировать: вы редактировали свой вопрос о назначении транзакций.

Цель транзакций действительно состоит в том, чтобы поддерживать базу данных в согласованном состоянии (чтение по ACID ), но программист должен решить, что согласовано. Посмотрите на ответ prodigitalson , чтобы увидеть пример возможного php-способа перехвата ошибок, который делает это для вас. Но пока вы находитесь в транзакции, другие процессы не увидят изменений, которые делает ваша транзакция - следовательно, атомарны и изолированы.

CREATE TABLE `testkeys` (
  `lid` INT,
  `column_name` VARCHAR(50),
  UNIQUE KEY `testuniq` (`lid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

BEGIN;
INSERT INTO testkeys(lid,column_name) VALUES(1,'test 1');
INSERT INTO testkeys(lid,column_name) VALUES(2,'test 2');
INSERT INTO testkeys(lid,column_name) VALUES(3,'test 3');
INSERT INTO testkeys(lid,column_name) VALUES(2,'test 2b');
COMMIT;
7 голосов
/ 27 января 2011

Чтобы добавить к тому, что сказал Конерак ... это упрощенный процесс с PDO вместо mysql, например:

$pdo = new PDO($mysqldsn, $user, $pass);
$pdo->beginTransaction();

try {

  $pdo->query("INSERT INTO list_columns(lid,column_name) VALUES(8,'test')");
  $pdo->query("INSERT INTO list_columns(lid,column_name) VALUES(8,'test')");
  $pdo->query("INSERT INT list_columns(lid,column_name) VALUES(8,'test')");
  $pdo->commit();

} catch (PDOException $e) {

  $pdo->rollBack();
  throw $e;
}
1 голос
/ 27 января 2011

Вам нужно проверить это вручную, и если есть какие-либо ошибки, вам нужно откатить его самостоятельно.

0 голосов
/ 20 мая 2019

Поскольку вы выполняете sql-запрос через php, он не будет работать так же, как в одной команде mysql. Для того, чтобы вышеуказанная транзакция работала, вам нужно обернуть свой код в блок try try и отключить mysql_autocommit, выполнить запрос вставки и использовать mysql_commit для подтверждения успешной работы или использовать mysql_rollback в блоке catch в случае возникновения ошибки.

$con=mysqli_connect("localhost","my_user","my_password","my_db");
try{
  mysqli_autocommit($con,FALSE);

  $query = "INSERT INTO list_columns(lid,column_name) VALUES(8,'test')";
  mysql_query($query);

  $query = "INSERT INTO list_columns(lid,column_name) VALUES(8,'test')";
  mysql_query($query);

  $query = "INSERT INT list_columns(lid,column_name) VALUES(8,'test')";
  mysql_query($query);

  mysql_commit($con);

}catch{

  mysql_rollback($con);

}
...