Intereting Posts
Как получить значения сеанса в Yii 2 Использование единой «умной цитаты» в моих данных JSON – это нарушение PHP-скрипта Получить Userinfo из Google OAuth 2.0 PHP API Отправка SMS с помощью модема GSM Как получить все после определенного персонажа? Как я могу получить список наиболее просматриваемых видеороликов Youtube дня по регионам? Какая лучшая передача функций – переменные или массивы / объекты? php pdo подготовить повторяющиеся переменные как читать xml-файл с URL-адреса, используя php Apache 2.2 не запускается после установки PHP 5.6 на Windows 8.1 Каков наилучший способ сделать аутентификацию пользователя в php? Как я могу запросить raw через Eloquent? Как предотвратить вставку электронной почты, если она уже существует с определенным идентификатором в laravel? Какие другие языки позволяют программистам использовать интерфейсы в качестве функциональных параметров? Почему PHP не имеет конструктора по умолчанию?

Как работает mysqli :: commit и mysqli :: rollback?

Я читал онлайн-руководство по php, но я все еще не уверен в том, как работают эти две функции: mysqli :: commit & mysqli :: rollback.

Первое, что я должен сделать, это:

$mysqli->autocommit(FALSE); 

Затем я делаю несколько запросов:

 $mysqli->query("..."); $mysqli->query("..."); $mysqli->query("..."); 

Затем я совершаю транзакцию, состоящую из этих 3 запросов, делая:

 $mysqli->commit(); 

НО в неудачном случае, когда один из этих запросов не работает, все 3 запроса отменяются или мне приходится называть откат самостоятельно? Я хочу, чтобы все 3 запроса были атомарными и считались только одним запросом. Если один запрос терпит неудачу, все 3 должны потерпеть неудачу и не будут иметь никакого эффекта.

Я спрашиваю об этом, потому что в комментариях, которые я видел на странице руководства: http://php.net/manual/en/mysqli.commit.php пользователь Lorenzo вызывает откат, если один из запросов не удался.

Что такое откат, если 3 запроса являются атомарными? Я не понимаю.

EDIT: Это пример кода, в котором я сомневаюсь:

 <?php $all_query_ok=true; // our control variable $mysqli->autocommit(false); //we make 4 inserts, the last one generates an error //if at least one query returns an error we change our control variable $mysqli->query("INSERT INTO myCity (id) VALUES (100)") ? null : $all_query_ok=false; $mysqli->query("INSERT INTO myCity (id) VALUES (200)") ? null : $all_query_ok=false; $mysqli->query("INSERT INTO myCity (id) VALUES (300)") ? null : $all_query_ok=false; $mysqli->query("INSERT INTO myCity (id) VALUES (100)") ? null : $all_query_ok=false; //duplicated PRIMARY KEY VALUE //now let's test our control variable $all_query_ok ? $mysqli->commit() : $mysqli->rollback(); $mysqli->close(); ?> 

Я думаю, что этот код неверен, потому что если какой-либо из запросов не удалось и $all_query_ok==false вам не нужно делать откаты, потому что транзакция не обрабатывалась. Я прав?

    Я думаю, что этот код неверен, потому что если какой-либо из запросов не удалось и $ all_query_ok == false, вам не нужно делать откаты, потому что транзакция не обрабатывалась. Я прав?

    Нет, транзакция не отслеживается при сбое одного SQL-Statement.

    Если какой-либо SQL-Statement не работает, оператор откатывается (как описано в ответе @ eggyal), но транзакция по-прежнему остается открытой. Если вы теперь вызываете commit , откат успешных утверждений не выполняется, и вы просто вставляете «поврежденные» данные в свою базу данных. Вы можете легко воспроизвести это:

     m> CREATE TABLE transtest (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL DEFAULT '', CONSTRAINT UNIQUE KEY `uq_transtest_name` (name)) ENGINE=InnoDB; Query OK, 0 rows affected (0.07 sec) m> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) m> INSERT INTO transtest (name) VALUE ('foo'); Query OK, 1 row affected (0.00 sec) m> INSERT INTO transtest (name) VALUE ('foo'); ERROR 1062 (23000): Duplicate entry 'foo' for key 'uq_transtest_name' m> INSERT INTO transtest (name) VALUE ('bar'); Query OK, 1 row affected (0.00 sec) m> COMMIT; Query OK, 0 rows affected (0.02 sec) m> SELECT * FROM transtest; +----+------+ | id | name | +----+------+ | 3 | bar | | 1 | foo | +----+------+ 2 rows in set (0.00 sec) 

    Вы видите, что вставка «foo» и «bar» прошла успешно, хотя второй SQL-оператор не удался – вы даже можете увидеть, что AUTO_INCREMENT было увеличено по ошибочному запросу.

    Таким образом, вы должны проверять результаты каждого query -call, и если один из них не работает, откатите вызов, чтобы отменить другие успешные запросы. Поэтому код Лоренцо в PHP-руководстве имеет смысл.

    Единственная ошибка, которая заставляет MySQL откатывать транзакцию, – это «тупик транзакции» (и это специфично для InnoDB, другие механизмы хранения могут обрабатывать эти ошибки по-разному).

    Как InnoDB разделе «Обработка ошибок InnoDB :

    Обработка ошибок в InnoDB не всегда такая же, как в стандарте SQL. Согласно стандарту, любая ошибка во время SQL-запроса должна приводить к откату этого оператора. Иногда InnoDB откатывает только часть отчета или всю транзакцию. Следующие пункты описывают, как InnoDB выполняет обработку ошибок:

    • Если у вас закончилось файловое пространство в табличном пространстве , возникает столбец MySQL Table is full и InnoDB откатывается от оператора SQL.

    • Сбой транзакции заставляет InnoDB откатывать всю транзакцию . Повторяйте всю транзакцию, когда это произойдет.

      Тайм-аут ожидания блокировки заставляет InnoDB откатывать только один оператор, ожидающий блокировки, и столкнулся с таймаутом. (Чтобы вернуть всю транзакцию транзакции, запустите сервер с параметром --innodb_rollback_on_timeout .) Повторите инструкцию, если используете текущее поведение, или всю транзакцию при использовании --innodb_rollback_on_timeout .

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

      Когда откат транзакции происходит из-за тайм-аута блокировки или блокировки ожидания, он отменяет действие операторов внутри транзакции. Но если в заявлении о начале транзакции были инструкции START TRANSACTION или BEGIN , откат не отменяет эту инструкцию. Другие операторы SQL становятся частью транзакции до появления COMMIT , ROLLBACK или некоторого оператора SQL, который вызывает неявное коммитирование.

    • Ошибка дублирующегося ключа возвращает запрос SQL, если вы не указали опцию IGNORE в своем заявлении.

    • row too long error возвращает запрос SQL.

    • Другие ошибки в основном обнаруживаются слоем кода MySQL (выше уровня ядра хранилища InnoDB ), и они откатывают соответствующий SQL-запрос. Замки не освобождаются при откате одного оператора SQL.