Как я могу настроить MySQL Innodb для обработки 1000 вставок в час?

10

У меня очень высокий трафик на сайте, где возможно добавление 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». Столы все Иннодб. Какие начальные настройки конфигурации и подход вы бы порекомендовали для решения этой проблемы?

Дайте мне знать, какая дополнительная информация вам может понадобиться.

Спасибо

user658182
источник
Вы начинаете со стандартным my.cnf для производства? Человек, ты должен оптимизировать это больше. Подробнее буду в моем ответе. :-)

Ответы:

11

Вы имеете дело с тупиком, а не с проблемой узкого места в производительности.

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

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

InnoDBможет показать вам подробную информацию о взаимоблокировке, запустив SHOW ENGINE INNODB STATUSв командной строке MySQL или с помощью mysql -uroot -p... -e "SHOW ENGINE INNODB STATUS".

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

К счастью, есть инструмент pt-deadlock-logger, который решает эту проблему, он заботится о InnoDBстатусе опроса и сохраняет всю подробную информацию о взаимоблокировке до того, как она будет обновлена ​​новым тупиком.

доблесть
источник
Хорошо знать! Я вижу в команде show status информацию о блокировке и связанных запросах и таблицах. Учитывая, что это в моем коде, как я могу использовать эту информацию из команды состояния, чтобы начать устранять проблему? Запрос PHP PDO довольно прост - подключите, подготовьте, выполните, повторите. Я был бы рад опубликовать любой код или сообщение о состоянии, если это поможет.
user658182
@ user658182 проверьте этот пост в stackoverflow о том, как бороться с взаимоблокировками: как избежать обнаружения взаимоблокировок mysql при попытке получить блокировку
Valor
1
@ max-vernon спасибо за редактирование синтаксиса, ясно английский, это не мой родной язык :-).
Доблесть
1
-е "ПОКАЗАТЬ СТАТУС ДВИГАТЕЛЯ INNODB"
символ
8

Это может быть так просто, как одна часть вашего кода, выполняющая транзакцию:

insert into t1...
insert into t2...
commit;

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

delete from t2 where...
delete from t1 where...
commit;

Если обе эти транзакции выполняются одновременно, может возникнуть условие гонки: первая транзакция не может быть изменена, t2поскольку она заблокирована второй транзакцией; в то время как вторая транзакция блокируется аналогичным образом, поскольку t1блокируется первой транзакцией. MySQL выбирает одну транзакцию как «жертву», в которой происходит сбой INSERT / UPDATE / DELETE. Приложению необходимо перехватить эту ошибку и повторить оператор - возможно, после паузы, чтобы у другой транзакции было время для завершения. Ничего общего с ограничениями емкости, просто неудачное время, которое может усугубляться тем, как устроен код. Переключитесь между DELETE в транзакции # 2 или INSERT в транзакции # 1, и тогда конфликт не возникнет - каждая транзакция будет ожидать доступа к нужной таблице (таблицам).

В MySQL 5.6 вы можете работать с включенной опцией innodb_print_all_deadlocks для сбора информации обо всех взаимоблокировках (не только самых последних) в журнале ошибок MySQL.

[Обязательный отказ от ответственности: я сотрудник Oracle. Выше мое личное мнение не официальное заявление.]

Макс Вебстер
источник