最近我们遇到一个MySQL的问题,分析后很有代表意义,特地写出来供大家参考。
出现问题是,数据库先是被置为只读,然后过了一段时间,MySQL直接Crash掉了
发生Crash时MySQL的error日志中打印了以下内容:
根据日志中我们可以看到,线程140363572082432要对记录上一个X锁,但是等待0x7fa949340740线程的RW-latch的释放
我们在向下看查询到如下信息(涉及到用户信息 谓词就用xxx代替):
根据上面信息我们去数据库中查看了这些select语句,发现执行计划都是全表扫描。
首先数据库变成了只读,最后数据库crash了,crash输出的信息如下:
InnoDB: Error: semaphore wait has lasted > 600 seconds 提示600秒没有响应 数据库选择了Crash 强制重启
从报错信息来看:
这里首先需要补充一下Latch的概念:Latch在MySQL中是用于保护高速缓冲区中共享数据的开发云主机域名,举个例子:
当我们执行select时,数据是缓存在buffer pool中的,多个线程并发访问或者修改这个数据必然需要一个并发控制机制,这个就是Latch
大家知道,数据库要访问的数据都必须先存在缓存中,而缓存一般比磁盘空间要小,数据缓存使用hash表来记录数据页是否在内存中。在Oracle中的并发控制比较精细:首先会对hash桶加latch,并根据hash桶查找对应的数据并加上pin,然后释放Latch。而MySQL相对没有控制得这么精细,对应的RW-Latch在errlog中说的很清楚,该RW-Latch是在buf0buf.cc的1069行创建的
RW-latch at 0x7fa949340740 created in file buf0buf.cc line 1069
对应的代码摘录如下:
跟踪源码,知道这个Latch是MySQL在数据库启动,初始化 innodb_buffer_pool时,将Latch创建好的。对应的函数调用过程:
正是由于这个RW-Latch被长时间占用了,其他的线程一直竞争不到,才导致了这个问题
这类问题的发生多数都是因为SQL写的不好,在表上面进行了大量的全表扫描占用了大量的Latch,解决方案就是避免SQL长时间占用latch:
修改数据库密码:[root@svr ~]#mysqladmin –uroot -p(旧密码) password ‘新密码’设置字体格式utf8[root@svr ~]#vim /etc/my.cnfcharacter_set_server=utf8进入数据库m…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。