图解MySQL | [缺陷分析] Table cache 导致 MySQL 崩溃

作者:黄炎 王悦 周海鸣(图解MySQL 公众号)

​引 言

本文是由爱可生研发团队出品的「图解MySQL」系列文章,不定期更新,但篇篇精品。
爱可生开源社区持续运营维护的小目标:

  • 每周至少推送一篇高质量技术文章
  • 每月研发团队发布开源组件新版
  • 每年1024开源一款企业级组件
  • 2019年至少25场社区活动

欢迎大家持续关注~

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


缺陷的现象

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

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

    图解MySQL | [缺陷分析] Table cache 导致 MySQL 崩溃_第1张图片
    image

缺陷的原理图解

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

图解MySQL | [缺陷分析] Table cache 导致 MySQL 崩溃_第2张图片
image

缺陷的原理说明

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

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

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

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


相关的知识点

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

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

  3. Hash结构,方便缓存的查找

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

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

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

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

  8. 参数的最小值是400

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


配置建议

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

扩展阅读

  1. 缺陷描述:
    https://bugs.mysql.com/bug.php?id=89126

  2. 描述如何打开和释放表定义的MySQL官方文档:
    https://dev.mysql.com/doc/refman/5.7/en/table-cache.html

image

近期社区动态

第三期 社区技术内容征稿

所有稿件,一经采用,均会为作者署名。

征稿主题:MySQL、分布式中间件DBLE、数据传输组件DTLE相关的技术内容

活动时间:2019年6月11日 - 7月11日

本期投稿奖励

投稿成功:京东卡200元*1

优秀稿件:京东卡200元*1+社区定制周边(包含:定制文化衫、定制伞、鼠标垫)

优秀稿件评选,文章获得****“好看****”****数量排名前三****的稿件为本期优秀稿件。

图解MySQL | [缺陷分析] Table cache 导致 MySQL 崩溃_第3张图片
image

你可能感兴趣的:(图解MySQL | [缺陷分析] Table cache 导致 MySQL 崩溃)