【问题标题】:Warning: A long semaphore wait警告:信号量等待时间长
【发布时间】:2014-09-11 15:56:14
【问题描述】:

在过去的 4 天里,我的夜间更新遇到了很多问题,除了 1 晚之外,这 4 天之间一切都很好。

在这些更新期间,我更新了几个全文索引。我是这样做的。

  1. 删除全文索引
  2. 更新全文表格
  3. 添加全文索引

这已经完美运行了 2 年多。通常更新时间约为 3-4 小时,这对于每晚更新的数据量来说是正常的。但从周五开始,更新时间确实在 9-12 小时之间!

昨晚服务器被引擎故意崩溃了,这是在错误日志中

InnoDB:警告:信号量等待很长: --线程 8676 在 dict0boot.ic 第 36 行等待了 241.00 秒,信号量:Mutex at 0000000053B0C1E8 创建了文件 dict0dict.cc 第 887 行,锁定 var 1 服务员标志 1 InnoDB:###### 启动 InnoDB 监控 30 秒以打印诊断信息:InnoDB:待处理的预读 0, 写入 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: corruption in the InnoDB 表空间。请参考 InnoDB: http://dev.mysql.com/doc/refman/5.6/en/forcing-innodb-recovery.html InnoDB:关于强制恢复。

我刚刚重新启动了服务器,一切正常,所以现在我正在等待在 bugs.mysql.com 中发布完整的错误报告

我在这个page 上发现了一些东西,似乎是同一类型的问题,但没有进一步的消息。

我不知道从哪里开始,我不知道为什么会突然发生这种情况。

我必须从这里提供什么样的详细信息?

  • 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 的简单更新查询很慢。 (8 秒内的 40000 条记录,通常在不到 1 的时间内完成)。

今天将继续尝试和微调它。

【问题讨论】:

  • @Darren,似乎是同一个问题,但由于没有提供更多信息,问题已关闭。
  • 我从this找到的。
  • @Darren 谢谢,我会立即查看。
  • 让我知道进展如何,这看起来是一个相当有趣的问题!

标签: mysql sql innodb alter-table full-text-indexing


【解决方案1】:

问题出在innodb_adaptive_hash_index

innodb_adaptive_hash_index=0 重启解决了问题。

正如问题中所述

“MySQL 5.6 及更高版本中的架构变化使工作负载增加 比以前更适合禁用自适应哈希索引 发布,尽管它仍然默认启用。”

这对我有用,因为我再也没有遇到同样的问题了。

【讨论】:

  • 是的,正如它在文档中建议的那样,它应该默认关闭但打开。但是,我有这个设置很长一段时间了。
  • 你能评论一下为什么会出现这个问题吗?
  • kaushal 的评论 “有错误。参数 innodb_adaptive_hash_index=0 对我有用”错误地发布为 answer
  • 它对我不起作用,因为现在默认情况下,innodb_adaptive_hash_index 是关闭的
【解决方案2】:

也遇到过这样的问题。数据库一天无故坏了好几次。我不确定这是否对我有帮助,但我的解决方案是优化所有表。三天至今,这个问题不再出现。

优化所有表的方法有很多,但我将通过 linux 控制台使用 PHP 为您提供一个示例

        #!/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

2019 年 7 月 17 日更新

我找到了导致我出现此错误的问题。

问题是我有一个包含 4,000 行的表。该表每秒接收大约 1000 次更新。此外,同时从这个表中,每秒大约有 500 个选项。通常,选择时间为 0.006 秒,但几天后选择时间变为 5 秒。在那之后,在队列中聚集了数千个选择的那一刻,出现了“A long semaphore wait”的错误。

可能的解决方案:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 2020-03-09
    • 2022-11-03
    • 2015-06-21
    • 2019-08-27
    相关资源
    最近更新 更多