ITPub博客

首页 > 数据库 > MySQL > 【Mysql】升级到MySQL 5.7的又一个理由——分区问题

【Mysql】升级到MySQL 5.7的又一个理由——分区问题

原创 MySQL 作者:小亮520cl 时间:2016-01-19 15:02:46 0 删除 编辑




  1. 前言


  1. 经常有小伙伴问Inside君,MySQL的分区(partition)怎么样?能用不?是不是有很多bug?不知MySQL的分区为何会给普罗大众这样的印象。但Inside君的印象中,分区影响比较大的bug就下面的一例(严格意义也很难说是bug),也是小伙伴们咨询Inside君分区遇到最多的问题。不过,好在这个bug已在5.7版本中得到了修复(准确来说是5.7支持了Native Paritition)。看来又多了一个升级到5.7的理由。总结来说,生产环境有必要每天弄个分区嘛?


  1. 正文

  1. 一个月之前,Scott和同事们发现公司有一个MySQL MHA集群的master(假设master机器名为hostA)每隔一周左右就会挂一次(指MySQL挂掉),在几周内,MHA来回切了好几次。
  2.  
  3.  按照国际惯例,Scott按照如下顺序去查问题到底出在哪里:
  4.  1. 先翻MySQL error log,没有发现异常
  5. 2. 再翻Linux系统日志文件,果然,翻到了下面的内容:

  6. Nov 26 13:05:38 hostA kernel: mysql invoked oom-killer: gfp_mask=0x280da, order=0, oom_adj=0, oom_score_adj=0
  7.  ......
  8.  Nov 26 13:05:38 hostA kernel: Out of memory: Kill process 32271 (mysqld) score 976 or sacrifice child
  9.  Nov 26 13:05:38 hostA kernel: Killed process 32271, UID 496, (mysqld) total-vm:83064212kB, anon-rss:64204132kB, file-rss:4544kB
  10.   

  11. 该机器的物理内存大小为62G,从上面的日志看,MySQL确实已经把它用满了。该机器上MySQL的innodb_buffer_pool=31G,Scott认为这已经相当保守了,而且各种buffer_size我们都使用的是默认值,MySQL OOM时的用户连接数是100+,
  12.  
  13.  这些目测都没有什么问题,但是居然还是发生了OOM,实在是不可思议。当时觉得就是内存不够用了呗,没有查出具体原因,后来62G的内存加到了125G(innodb_buffer_pool_size增大到64G,这值确实很保守),还是发生了OOM。
  14.  
  15.  其实一开始Scott就发现,这台机器上有一个更早的问题,就是因为系统最大文件打开数不够导致这台机器的xtrabackup备份总是不成功,具体是什么原因请等Scott去整理xtrabackup备份的更详细的过程。然后我去检查了该机器上面的*.ibd文件和*.frm文件数量,吓我一跳(话说Inside君也是吓尿了):

  16. [userA@hostA mysql]$ sudo find . -name '*.ibd' | wc -l
  17. 169577
  18. [userA@hostA mysql]$ sudo find . -name '*.frm' | wc -l
  19. 2534

  20.  也就是说,该机器上面竟然有17万个ibd文件,但是只有2534张表,很明显是分区表中的分区数量非常多。
  21.  
  22.  [userA@hostA mysql]$ sudo find . -name '*par*' | wc -l
  23.  1882
  24.  
  25.  Scott仔细比较了这台机器和其他没有问题的机器的不同,发现这台机器上面分区数量太多是唯一的一个不同,这让Scott没有办法不怀疑是分区导致的问题。
  26.  
  27.  Scott仍然按照国际惯例,第一时间去查MySQL 5.6的官方文档,无果。。。(官方文档虽然不是万能的,但是仍然是出现问题的第一参考资料)。去MySQL的bugs页面搜索关于partition的bug,无果。。。去google了下,发现有的比较杂的网站上面写道MySQL分区数量太多引发内存耗尽的问题,但是文章讲的内容感觉不是很正确。
  28.  
  29.  最后在姜老师的指点下,看了这篇文章:
  30.  
  31.  http://mysqlserverteam.com/innodb-native-partitioning-early-access/
  32.  
  33.  上面是MySQL开发团队写的关于InnoDB Native Partitioning的文章。文章中大概讲的内容是,在5.6里面,分区的信息是在MySQL Server层维护的(在.par文件里面),InnoDB引擎层是不知道有分区这个概念的,InnoDB引擎层把每一个分区都当成一张普通的InnoDB表。在打开一个分区表时,会打开很多个分区,打开这些分区表就相当于打开了同等数量的InnoDB表,这需要更多内存存放InnoDB表的元数据和各种与ibd文件打开相关的各种cache与handler的信息。在5.7里面,InnoDB引入了Native Partitioning,它把分区的信息从Server层移到了InnoDB层,打开一个分区表和打开一个InnoDB表的内存开销基本是一样的。
  34.   
  35. If we compare the amount of memory used when opening a single instance of this table, first using the old generic non-native partitioning, and then with InnoDB Native Partitioning we see the following:
  36.   
  37. One open instance of the table takes 49% less memory (111MB vs 218MB) with the current state of Native Partitioning support. With ten open instances of the table, we take up 90% less memory (113MB vs 1166MB)!

  38. 由于升级到5.7还需要一些时日,目前已经将分区数量减少到25000,125G剩余内存在20天里一直稳定在20G左右,这也表明确实是分区数量太多的原因。



来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29096438/viewspace-1979021/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
毕业以后专业任职数据库工程师职位,itpub一直作为自己的笔记记录的地方,blog写的不详细,草书笔记,仅供参考!

注册时间:2013-09-12

  • 博文量
    529
  • 访问量
    1126924