PDO ложно-положительный тупик - PullRequest
1 голос
/ 11 октября 2019

Мы запускаем базовое веб-приложение на PHP 7.0 и MariaDB 10.0. Каждый запрос поступает в базу данных через класс PDO.

Проблема в том, что PDO иногда выдает исключение взаимоблокировки:

SQLSTATE [40001]: ошибка сериализации: 1213 Обнаружена взаимоблокировка при попытке получить блокировку;попробуйте перезапустить транзакцию

Но когда я смотрю в MariaDB спецификации взаимоблокировки (используя SHOW ENGINE INNODB STATUS), «последний тупик» не является настоящим последним тупиком. Например, показывается тупик с 2019-10-01, но PDO предупредил меня о последнем тупике 2019-10-05. Это похоже на то, что PDO создает тупики. Но опять же - это не каждый раз. И свойство MariaDB "тупики Innodb" (int) не увеличивается, когда последний тупик не отображается в "SHOW ENGINE INNODB STATUS".

Это происходит только для одной транзакции в это время. Все таблицы в транзакции работают на движке InnoDB. Это около 40 запросов (выбрать, обновить, вставить). Свойство MariaDB "innodb print all deadlocks" включено. Для подключения доступен только один сервер базы данных.

PDO просто сообщает обо всех ошибках из базы данных или может "создать тупики"? Или это может быть проблема старых версий PHP и MariaDB? Мы планируем обновить, но не сейчас.

И точно: я не собираюсь решать этот текущий тупик, но всю эту ненормальность.


РЕДАКТИРОВАТЬ: Iвыяснилось, что этот текущий тупик не был "составлен" PDO. Это был настоящий тупик, но проблема заключалась в запросе « TRUNCATE » в другой транзакции (задание cron).

Длинное описание:

Предположим, таблица x1 и таблица x2ссылка на первичный ключ x1. История была такой:

  1. первая транзакция: вставьте строку в таблицу x1;
  2. вторая транзакция: TRUNCATE table x2;(ожидание блокировки)
  3. первая транзакция: обновить вставленную строку в таблице x1;

И третий шаг вызвал взаимоблокировку. Хотя первичный ключ из вставленной строки таблицы x1 в действительности не был в таблице x2. Таблица x2 просто ссылалась на x1.

1 Ответ

0 голосов
/ 17 октября 2019

Если вы используете TRUNCATEing в качестве шага замены содержимого, измените на:

CREATE TABLE x LIKE real;
load data into x
RENAME TABLE real TO old,
             x TO real;
DROP TABLE old;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...