У меня очень высокий трафик на сайте, где возможно добавление 1000 новых записей каждый час.
Эта ошибка наносит вред сайту:
PDOException: SQLSTATE[40001]: Serialization failure: 1213
Deadlock found when trying to get lock;
try restarting transaction: INSERT INTO {location_instance}
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0,
:db_insert_placeholder_1, :db_insert_placeholder_2,
:db_insert_placeholder_3, :db_insert_placeholder_4);
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] =>
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] =>
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )
Я был бы очень удивлен, если бы MySQL не мог справиться с этим типом нагрузки. Итак, мои вопросы таковы: это проблема с базой данных и как я могу настроить MySQL для обработки такого большого трафика?
У меня есть копия моего сайта, настроенная на сервере разработки со сценариями, которые имитируют загрузку контента, добавляемого на сайт. Я использую Ubuntu, стек LAMP, с 16 ГБ оперативной памяти.
Правда, я не очень разбираюсь в базах данных. Фактически, я начинаю с файла my.cnf по умолчанию, который поставляется вместе с ним после завершения «apt-get install». Столы все Иннодб. Какие начальные настройки конфигурации и подход вы бы порекомендовали для решения этой проблемы?
Дайте мне знать, какая дополнительная информация вам может понадобиться.
Спасибо
Ответы:
Вы имеете дело с тупиком, а не с проблемой узкого места в производительности.
Если у вас есть тысяча новых записей в час, вы очень далеки от достижения пределов MySQL. MySQL может выдержать нагрузку как минимум в 50 раз.
Блокировки возникают из-за кода приложения и не являются ошибкой сервера базы данных. Взаимные блокировки не могут быть исправлены на стороне сервера MySQL, за исключением некоторых конкретных ситуаций.
InnoDB
может показать вам подробную информацию о взаимоблокировке, запустивSHOW ENGINE INNODB STATUS
в командной строке MySQL или с помощьюmysql -uroot -p... -e "SHOW ENGINE INNODB STATUS"
.Однако это показывает только последнюю возникшую взаимоблокировку, журнал тупиковых ситуаций отсутствует.
К счастью, есть инструмент pt-deadlock-logger, который решает эту проблему, он заботится о
InnoDB
статусе опроса и сохраняет всю подробную информацию о взаимоблокировке до того, как она будет обновлена новым тупиком.источник
Это может быть так просто, как одна часть вашего кода, выполняющая транзакцию:
в то время как другая часть вашего кода изменяет те же таблицы в другом порядке:
Если обе эти транзакции выполняются одновременно, может возникнуть условие гонки: первая транзакция не может быть изменена,
t2
поскольку она заблокирована второй транзакцией; в то время как вторая транзакция блокируется аналогичным образом, посколькуt1
блокируется первой транзакцией. MySQL выбирает одну транзакцию как «жертву», в которой происходит сбой INSERT / UPDATE / DELETE. Приложению необходимо перехватить эту ошибку и повторить оператор - возможно, после паузы, чтобы у другой транзакции было время для завершения. Ничего общего с ограничениями емкости, просто неудачное время, которое может усугубляться тем, как устроен код. Переключитесь между DELETE в транзакции # 2 или INSERT в транзакции # 1, и тогда конфликт не возникнет - каждая транзакция будет ожидать доступа к нужной таблице (таблицам).В MySQL 5.6 вы можете работать с включенной опцией innodb_print_all_deadlocks для сбора информации обо всех взаимоблокировках (не только самых последних) в журнале ошибок MySQL.
[Обязательный отказ от ответственности: я сотрудник Oracle. Выше мое личное мнение не официальное заявление.]
источник