PDO, mysql, транзакции и блокировка таблицы

Для удовольствия я заменяю расширение 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;... и т.д.".

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

Ответы

Ответ 1

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

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

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

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

Ответ 2

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

Итак, вы можете сделать:

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

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

Ответ 3

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

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

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

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

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

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

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

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

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