Table cache 导致 MySQL 崩溃

本文分析的缺陷是MySQL Bug #89126,其主要现象是:在使用很多表的数据库中,执行create table会导致数据库崩溃。

缺陷的现象

在MySQL中创建大量表,填满 InnoDB的表定义缓存 (缓存的大小配置参看后文)。

继续执行create table ...,有一定概率使得MySQL在如下堆栈或类似堆栈崩溃:

缺陷的原理图解

(请将手机横过来查看图解)

缺陷的原理说明

图2,create table ...向缓存中插入了新的表定义,并持有了表定义的引用,但代码中又将表定义释放了

图3,InnoDB在此时刚好进行缓存回收,回收掉了已经释放的表定义。

图4,create table ...继续进行,使用了表定义的引用,由于使用了被回收的内存地址,MySQL继而崩溃。

对缺陷的修复:第1步的行为变更为不释放表定义,从而在第2步中表定义不会回收 (目前这个修复方法尚未被官方接受)。

相关的知识点

表定义缓存 (table cache):InnoDB 会对表定义进行缓存,以减少不停读取表定义文件造成的IO压力。

缓存的内部同时维护了两个数据结构:

Hash结构,方便缓存的查找

LRU (Least Recently Used) 结构,方便缓存的回收

InnoDB 对缓存进行定时回收,回收策略分为忙时闲时两种策略,用于减少回收动作造成的负担。

缓存的容量可临时超过其限制大小。这个设计与定时回收有关。

缓存的容量上限通过参数table_definition_cache设置:

参数的最小值是400

默认值是通过以下公式计算得出:min(400+table_open_cache/2),2000)

配置建议

除非有上万张表,一般建议设置table_definition_cache值略大于表数量,使缓存能够容纳所有的表定义

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180526G02GNB00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券