Предупреждение: долгое семафорное ожидание

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

Во время этих обновлений я обновляю пару полнотекстовых индексов. Я делаю это таким образом.

  • Падение полнотекстового индекса
  • Обновить полнотекстовую таблицу
  • Добавить индекс полного текста

Это работает идеально подходит более 2 лет. Обычное время обновления составляло около 3-4 часов, что было нормальным для количества данных, которые обновляются каждую ночь. Но с пятницы действительно время обновления было между 9-12 часов!

Вчера вечером сервер неожиданно разбился на двигатель, это было в журнале ошибок

InnoDB: предупреждение: долгое семафорное ожидание: --Thread 8676 ждал в строке dict0boot.ic 36 в течение 241.00 секунд семафор: Mutex при 0000000053B0C1E8 создал файл dict0dict.cc строка 887, lock var 1 флаг официантов 1 InnoDB: ###### Запуск InnoDB Монитор в течение 30 секунд для печати диагностической информации: InnoDB: Ожидающие предварительные 0, pwrites 0

InnoDB: ###### Диагностическая информация, напечатанная в стандартном потоке ошибок InnoDB: Ошибка: ожидание семафора длилось > 600 секунд. InnoDB: Мы намеренно сбой сервера, потому что он, кажется, висит. 2014-07-21 05:20:54 1384 InnoDB: ошибка утверждения в потоке 4996 в файл srv0srv.cc строка 1748

InnoDB: Мы намеренно генерируем ловушку памяти. InnoDB: Отправить подробный отчет об ошибках http://bugs.mysql.com. InnoDB: Если вы получаете повторные ошибки утверждения или сбои, даже InnoDB: сразу после при запуске mysqld может быть InnoDB: коррупция в InnoDB табличного пространства. Пожалуйста, обратитесь к InnoDB: http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.htmlInnoDB: о принудительном восстановлении.

Ive только что перезапустил сервер, и все прошло нормально, так что теперь я жду, чтобы опубликовать полный отчет об ошибке в файле bugs.mysql.com

Я обнаружил что-то на этой странице, и это похоже на ту же проблему, но никаких дальнейших сообщений tho.

Я не знаю, куда идти отсюда, я не знаю, почему это происходит внезапно.

Какие подробности я могу предоставить здесь?

  • Версия сервера Mysql: 5.6.13
  • sort_buffer_size = 2M
  • innodb_buffer_pool_size = 53G
  • innodb_log_buffer_size = 4M
  • innodb_flush_log_at_trx_commit = 0
  • innodb_log_file_size = 25G

ИЗМЕНИТЬ

После чтения this, в нем говорится, что

"Архитектурные изменения в MySQL 5.6 и выше делают больше рабочих нагрузок подходит для отключения адаптивного хеш-индекса, чем в предыдущем релизы, хотя по-прежнему он включен по умолчанию."

Я отключил адаптивный хеш-индекс, используя  SET GLOBAL innodb_adaptive_hash_index=0 и теперь я пытаюсь проверить, исправлена ​​ли проблема. Ситуация точно так же как и ночью.


Ночное обновление:

Обновление прошло отлично. Менее 6 часов. Не было никаких проблем с обновлением полного текста, однако я все же нашел, что простой запрос на обновление с JOIN был медленным. (40000 записей в 8 секунды, что обычно выполнялось менее чем 1).

Будет продолжаться и сегодня, чтобы попытаться настроить его.

Ответ 1

Проблема заключалась в innodb_adaptive_hash_index

innodb_adaptive_hash_index=0, и перезагрузка решила проблему.

Как указано в вопросе

"Архитектурные изменения в MySQL 5.6 и выше делают больше рабочих нагрузок подходит для отключения адаптивного хеш-индекса, чем в предыдущем релизы, хотя по-прежнему он включен по умолчанию."

Это сработало для меня, поскольку у меня еще не было такой же проблемы.

Ответ 2

Была и такая проблема. База данных ломалась без причины несколько раз в день. Я не уверен, помогло ли это мне, но мое решение - оптимизировать все таблицы. Пока три дня эта проблема больше не появляется.

Существует много способов оптимизации всех таблиц, но я приведу пример того, как сделать это с помощью PHP через консоль linux.

        #!/bin/php -n
        <?php
    // /bin/php -n /sysmyx/mysql/hand_optimize_all_tables.php
    dl('mysqlnd.so');
    dl('mysqli.so');
$timestart  = time();
$n=0;
$con=mysqli_connect("localhost","roootmysql","passss");

if (mysqli_connect_errno())  {  echo "mysql error".PHP_EOL;
exit;
}
mysqli_query($con,"SET GLOBAL innodb_buffer_pool_dump_now = 1");
$res = mysqli_query($con,"SHOW DATABASES");
while ($row = mysqli_fetch_assoc($res)) {
$db_name=$row['Database'];
if ($db_name!="mysql" && $db_name!="information_schema" && $db_name!="performance_schema" && $db_name!="" && $db_name!="sys") {
echo '*'.$db_name.'*'.PHP_EOL;
//!!!!!!!!!!!!!!!!!!!!!!!// $query="SHOW TABLE STATUS FROM $db_name where Data_free>0;";
$query="SHOW TABLE STATUS FROM $db_name";
$tabbll=mysqli_query($con,$query);
while ($row2 = mysqli_fetch_assoc($tabbll)) {
$n++;
$opt_table='''.$db_name.''.''.$row2['Name'].''';
$query2="OPTIMIZE TABLE $opt_table";
$time1 = time();
mysqli_query($con,$query2);
$time2 = time();
$time3 = $time2-$time1;
echo $n.' '.$time3.' '.$row2['Data_free'].' '.$opt_table.PHP_EOL;
}}}
mysqli_query($con,"SET GLOBAL innodb_buffer_pool_load_now = 1");
mysqli_close($con);
$timeend  = time();
$time  = $timeend-$timestart;
?>

Также часть настроек my.cnf

innodb_thread_concurrency=0
flush_time=0
innodb_adaptive_hash_index=0
innodb_adaptive_hash_index_parts=1
innodb_purge_threads=1
innodb_fatal_semaphore_wait_threshold=60

ОБНОВЛЕНИЕ 17-07-2019

Я нашел проблему, которая вызвала у меня эту ошибку.

Проблема была в том, что у меня была таблица из 4000 строк. Эта таблица получала около 1000 обновлений каждую секунду. Кроме того, из этой таблицы одновременно, около 500 выборок каждую секунду. Обычно время выбора составляет 0,006 секунды, но через несколько дней время выбора становится 5 секунд. После этого, в тот момент, когда тысячи очередей были собраны в очереди, и наступил момент ошибки "Долгое ожидание семафора".

Возможные решения:

1) Создайте другую структуру таблицы, проверьте индиксы, разбейте таблицу на несколько таблиц.

2) Раз в несколько часов оптимизируйте таблицу.

3) Придумайте систему кеширования для этой таблицы.

Возможные проблемы поиска:

Полезный скрипт, который поможет вам увидеть, какие запросы собираются во время сбоя mysql. Запускайте скрипт каждую минуту через cron.

#!/bin/bash 
USER=$(</sys_snting/mysql_user)
PASSWORD=$(</sys_snting/mysql_pass)
num=$(mysql --user=$USER --password=$PASSWORD -s -N -e "SELECT count(*) FROM information_schema.processlist ;")
if [ $num -ge 500 ] ; then
mysql --user=$USER --password=$PASSWORD -e "show full processlist" > /media/bug/$(date +%Y%m%d%H%M%S)_$num.txt
echo $num

# Kill selections that can lead to "A long semaphore wait"
# mysql --user=$USER --password=$PASSWORD -N -e "SELECT Id FROM information_schema.processlist where INFO like '%SELECT \'d_narfe\' FROM \'maitableep_com\'.\'5000_active\' WHERE%';" | while IFS= read -r loop
# do
#     echo "$loop"
# mysqladmin --user=$USER --password=$PASSWORD  kill $loop
# done 
fi