PDO, mysql, транзакции и блокировка таблиц - PullRequest
14 голосов
/ 24 июня 2010

Ради интереса я заменяю расширение mysqli в своем приложении на PDO.

Иногда мне нужно использовать транзакции + блокировку таблиц.

В этих ситуациях, согласно руководству по mysqlСинтаксис должен быть немного другим.Вместо того чтобы вызывать START TRANSACTION, вы делаете это так ...

SET autocommit=0;
LOCK TABLES t1 WRITE, t2 READ, ...;
... do something with tables t1 and t2 here ...
COMMIT;
UNLOCK TABLES;

(http://dev.mysql.com/doc/refman/5.0/en/lock-tables-and-transactions.html)

Мой вопрос: как это взаимодействует с PDO :: beginTransaction? Могу ли я использоватьPDO :: beginTransaction в этом случае? Или я должен вручную отправить sql "SET autocommit = 0; ... etc".

Спасибо за совет,

Ответы [ 3 ]

9 голосов
/ 19 ноября 2012

Когда вы вызываете PDO :: beginTransaction () , он отключает автоматическую фиксацию.

Так что вы можете сделать:

$db->beginTransaction();
$db->exec('LOCK TABLES t1, t2, ...');
# do something with tables
$db->commit();
$db->exec('UNLOCK TABLES');

После фиксации () или rollBack () база данных вернется в режим автоматической фиксации.

6 голосов
/ 24 июня 2010

В MySQL начало транзакции отличается от выключения автоматической фиксации из-за того, как работает LOCK / UNLOCK TABLES.В MySQL LOCK TABLES фиксирует любые открытые транзакции, но отключение автоматической фиксации фактически не запускает транзакцию.MySQL забавен в этом смысле.

В PDO запуск транзакции с использованием beginTransaction фактически не запускает новую транзакцию, он просто отключает автокоммит.В большинстве баз данных это нормально, но может иметь побочные эффекты с упомянутым поведением MySQL.

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

Вы можете свободно смешивать методы API PDO для работы с транзакциями и командами SQL, если не работаете с странностями MySQL.

4 голосов
/ 12 сентября 2016

Я потратил огромное количество времени на обход этой проблемы, и документация PHP в этой области в лучшем случае расплывчатая.Несколько вещей, которые я обнаружил, работая с PHP 7 с таблицей MySQL InnoDB:

PDO :: beginTransaction не просто отключает автокоммит , проверив ответ, предоставленный Ольховским, с кодом, которыйсбои, откаты не работают;нет транзакционного поведения.Это означает, что это не может быть так просто.

Начало транзакции может блокировать используемые таблицы ... Я с нетерпением жду, когда кто-нибудь скажет мне, что я не прав с этим, ноВот причины, по которым это может быть: Этот комментарий , который показывает, что таблица недоступна при запуске транзакции без блокировки. Эта страница документации PHP , которая вставляется в конце:

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

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

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

Обновление У меня был рабочий сервер, работающий с использованием функций транзакций PDO некоторое времятеперь, недавно используя базу данных Aurora AWS (полностью совместима с MySQL, но создана для автоматического масштабирования и т. д.).Я доказал эти два момента самому себе:

  • Транзакции (просто возможность фиксировать все изменения базы данных вместе) работают с использованием PDO :: beginTransaction ().Короче говоря, я знаю, что многие сценарии потерпели неудачу на полпути при выборе / обновлении базы данных, и была сохранена целостность данных.
  • Блокировка таблицы не происходит, у меня была ошибка дублирования индекса, чтобы доказать это.

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

...