背景

近期线上MySQL 5.7.20集群不定期(多则三周,短则一两天)出现主库mysql crash、触发主从切换问题,堆栈信息如下;

从堆栈信息可以明显看出,在调用 try_acquire_lock_impl 时触发的crash。

分析

在官方Bug库未搜到类似问题,转而从代码库入手,搜到对应的BUG —— 8bc828b982f678d6b57c1853bbe78080c8f84e84

BUG#26502135: MYSQLD SEGFAULTS IN

              MDL_CONTEXT::TRY_ACQUIRE_LOCK_IMPL

ANALYSIS:
=========
Server sometimes exited when multiple threads tried to
acquire and release metadata locks simultaneously (for
example, necessary to access a table). The same problem
could have occurred when new objects were registered/
deregistered in Performance Schema. The problem was caused by a bug in LF_HASH - our lock free
hash implementation which is used by metadata locking
subsystem in 5.7 branch. In 5.5 and 5.6 we only use LF_HASH
in Performance Schema Instrumentation implementation. So
for these versions, the problem was limited to P_S. The problem was in my_lfind() function, which searches for
the specific hash element by going through the elements
list. During this search it loads information about element
checked such as key pointer and hash value into local
variables. Then it confirms that they are not corrupted by
concurrent delete operation (which will set pointer to 0)
by checking if element is still in the list. The latter
check did not take into account that compiler (and
processor) can reorder reads in such a way that load of key
pointer will happen after it, making result of the check
invalid. FIX:
====
This patch fixes the problem by ensuring that no such
reordering can take place. This is achieved by using
my_atomic_loadptr() which contains compiler and processor
memory barriers for the check mentioned above and other
similar places. The default (for non-Windows systems) implementation of
my_atomic*() relies on old __sync intrisics and implements
my_atomic_loadptr() as read-modify operation. To avoid
scalability/performance penalty associated with addition of
my_atomic_loadptr()'s we change the my_atomic*() to use
newer __atomic intrisics when available. This new default
implementation doesn't have such a drawback.

大体含义是:

当多个线程分别同时获取、释放metadata locks时,或者在 Performance Schema 中注册/撤销新的object时,可能会触发该问题,导致 mysql server crash。

该问题是 LF_HASH(Lock-Free Extensible Hash Tables) 的BUG引起的,那么 LF_HASH 用在什么地方呢?

  1. 在5.5、5.6中只用在 Performance Schema Instrumentation 模块。
  2. 在5.7中也用于metadata加锁模块。

问题出在my_lfind() 函数中,该函数针对cursor->prev的判断未考虑CAS,该patch通过使用 my_atomic_loadptr() 解决了该问题:

diff --git a/mysys/lf_hash.c b/mysys/lf_hash.c
index dc019b07bd9..3a3f665a4f1 100644
--- a/mysys/lf_hash.c
+++ b/mysys/lf_hash.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -83,7 +83,8 @@ retry:
do { /* PTR() isn't necessary below, head is a dummy node */
cursor->curr= (LF_SLIST *)(*cursor->prev);
_lf_pin(pins, 1, cursor->curr);
- } while (*cursor->prev != (intptr)cursor->curr && LF_BACKOFF);
+ } while (my_atomic_loadptr((void**)cursor->prev) != cursor->curr &&
+ LF_BACKOFF);
for (;;)
{
if (unlikely(!cursor->curr))
@@ -97,7 +98,7 @@ retry:
cur_hashnr= cursor->curr->hashnr;
cur_key= cursor->curr->key;
cur_keylen= cursor->curr->keylen;
- if (*cursor->prev != (intptr)cursor->curr)
+ if (my_atomic_loadptr((void**)cursor->prev) != cursor->curr)
{
(void)LF_BACKOFF;
goto retry;

解决

查看change log,该问题在5.7.22版本修复的:

A server exit could result from simultaneous attempts by multiple threads to register and deregister metadata Performance Schema objects, or to acquire and release metadata locks. (Bug #26502135)

升级内核版本到5.7.29,之后巡检1个月,该问题未再出现,问题解决。

PS:

篇幅有限,在后续文章中会单独分析 MDL、LF_HASH 源码,敬请关注。


欢迎关注我的微信公众号【MySQL数据库技术】。

知乎 - 数据库技术 专栏: https://zhuanlan.zhihu.com/mysqldb

思否/segmentfault: https://segmentfault.com/u/dbtech

开源中国/oschina: https://my.oschina.net/dbtech

掘金: https://juejin.im/user/5e9d3ed251882538083fed1f/posts

博客园/cnblogs: https://www.cnblogs.com/dbtech

捉虫日记 | MySQL 5.7.20 try_acquire_lock_impl 异常导致mysql crash的更多相关文章

  1. Linux 文件系统引起的云盘文件系统异常导致 MySQL 数据页损坏事故恢复复盘

    事故的起因是因为当我访问某个数据库的某个表的时候,MySQL 立即出现崩溃并且去查看 MySQL 的错误日志出现类似信息 --09T05::.232564Z [ERROR] InnoDB: Space ...

  2. 记录一次更改服务器名称导致mysql 不能正常登录、启动

    由于客户要求更改服务器的名称,以便区分多台服务器:修改前mysql 能正常登录,但是修改后,登录时报错: Enter password: ERROR 1524 (HY000): Plugin '*C6 ...

  3. 捉虫记(四)线程安全导致的HighCpu

    一个朋友QQ群里说网站启动后会cpu很高,想要帮忙看一下dump. 1.打开windbg加载dump文件后第一个命令lmf,这个命令显示加载的dll以及路径,这样子可以找个dll来帮忙加载sos,(额 ...

  4. [MySQL Reference Manual] 20 分区

    20 分区 20 分区 20.1 MySQL的分区概述 20.2 分区类型 20.2.1 RANGE分区 20.2.2 LIST分区 20.2.3 COLUMNS分区 20.2.3.1 RANGE C ...

  5. mysql 5.6.20的安装、配置服务、设置编码格式

    一.安装 安装环境        系统:Window 32        版本:Mysql 5.6.20 1. 首先从官网上http://dev.mysql.com/downloads/mysql/ ...

  6. win 2012 安装mysql 5.7.20 及报错 This application requires Visual Studio 2013 Redistributable. Please install the Redistributable then run this installer again 的解决办法

    本文地址:http://www.cnblogs.com/jying/p/7764147.html    转载请注明出处. 安装过程其实挺简单,基本上下一步下一步,可以参考我的另一篇mysql安装文章: ...

  7. Windows 64 位 mysql 5.7.20 安装教程

    mysql 5.7以上版本包解压中没有data目录和my-default.ini和my.ini文件以及服务无法启动的解决办法以及修改初始密码的方法 mysql官网下载地址:https://dev.my ...

  8. Windows 下 MySql 5.7.20安装及data和my.ini文件的配置(转)

    Windows 下 MySql 5.7.20安装及data和my.ini文件的配置     本文通过图文并茂的形式给大家介绍了MySql 5.7.20安装及data和my.ini文件的配置方法. my ...

  9. CentOS 7.4 使用源码包编译安装MySQL 5.7.20

    使用yum安装的MySQL一般版本比较旧,但是运行稳定.如果想要尝试最新的功能或者需要指定特殊的功能的话,就需要手工进行编译安装了. 一.下载安装包 (一).先下载MySQL源码,网址为:https: ...

随机推荐

  1. 17 shell break与continue

    使用 while.until.for.select 循环时,如果想提前结束循环(在不满足结束条件的情况下结束循环),可以使用 break 或者 continue 关键字. 在C语言.Python.Ja ...

  2. 使用robot合并Robot Framework测试报告

    p.p1 { margin: 0; font: 17px ".PingFang SC" } p.p2 { margin: 0; font: 12px "Helvetica ...

  3. IDEA部署了项目,其他页面可以正常访问,但访问tomcat的localhost:8080却出现404

    解决方案 点击Edit Configurations 点击右边的加号, 把目录放在你tomcat目录下的ROOT目录.之后就可以正常运行了

  4. flask的常规使用二

    一.路由(router) 路由指定了url 到函数之间的一个映射关系. url ---> flask框架拿到url 的路径部分和路由中的内容进行匹配,如果匹配成功了则执行对应的函数.如果没有找到 ...

  5. 全彩LED灯

    1.全彩 LED 灯,实质上是一种把红.绿.蓝单色发光体集成到小面积区域中的 LED 灯,控制时对这三种颜色的灯管输出不同的光照强度,即可混合得到不同的颜色,其混色原理与光的三原色混合原理一致.例如, ...

  6. .Net Core微服务——服务发现:Consul(一)

    先思考一些问题:它是做什么的.以及怎么使用它.带着这些问题往下走. consul是做什么的 consul用于微服务下的服务治理.服务治理是什么?它包含但不限于:服务发现.服务配置.健康检查.键值存储. ...

  7. VS Code 下载安装并设置中文面板显示

    下载: 下载地址:https://code.visualstudio.com/ 微软在2015年4月30日Build 开发者大会上正式宣布了 Visual Studio Code 项目:一个运行于 M ...

  8. 数据库里的回车字符导致取过来的json字符串不规范的问题

    转发:https://bbs.csdn.net/topics/380192638 你可以报保存数据库之前,进行 替换 str = str.Replace("\r\n"," ...

  9. Kubernetes实战:高可用集群的搭建和部署

    摘要:官方只提到了一句"使用负载均衡器将 apiserver 暴露给工作节点",而这恰恰是部署过程中需要解决的重点问题. 本文分享自华为云社区<Kubernetes 高可用集 ...

  10. Python开发篇——构建虚拟Python开发环境(Conda+Poetry)

    前言 之前虽略有提及Python,但是没有实际地写点料.惭愧,惭愧,所以这次先起个头,讲讲如何构建虚拟Python开发环境.相信之前看过我博客的人可能会想:博主不会又要聊聊Docker吧?放心,不会. ...