[转帖]mysql TableMap id递增有关问题_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2110 | 回复: 0   主题: [转帖]mysql TableMap id递增有关问题        下一篇 
fozhyn
注册用户
等级:上士
经验:317
发帖:101
精华:0
注册:2011-10-18
状态:离线
发送短消息息给fozhyn 加好友    发送短消息息给fozhyn 发消息
发表于: IP:您无权察看 2014-11-25 15:36:52 | [全部帖] [楼主帖] 楼主

背景

   这两天在线上运行的mysql数据库同步,过个1,2天就爆了一次内存,所以dump了一下jvm内存信息分析了下,发觉就是tablemap对象的cache是一个罪魁祸首,2G的old区,平均被4个同步任务划分掉。

   解释下,缓存tablemap的意义:

   a.  insert/update/delete语句操作数据库时,在binlog中会产生两条binary log,第一条就是table map,告诉你改了的表信息。第二条才是具体的变更操作,通过一个tableId进行关联。

   b.  通过tableId缓存,可以在执行insert/update/delete解析的时候能够知道具体的表信息,然后根据schema + table name去反查一次数据库,获取字段名字,主键等信息。

   一般传统意义上的理解,tableId可以说是相对不太会变化,出现ddl操作时才会发生一次变化,所以这样的cache逻辑一直运行了1年多也没出过问题。

分析

   首先查询是否出现频繁的ddl变更,不过很可悲的是,查了半天发现最近几天没有发生过ddl操作,那table_id的频繁递增到底是因为什么原因?  

   网上找到一篇分析了table_id实现的文章: MySQL Binlog中TABLE ID源码分析

   文章中提到几点:

mysql会缓存table def,每次在写入binlog时,直接存入table def中关联的id. 

比如有新的table变更时,在cache中没有,就会触发一次load table def的操作,此时就会在原先最后一次table_id基础上+1,做为新的table def的id

table cache如果超过限制,就会清理最久没用的table def (有点类似LRU)

   所以如果table def cache过小,就会出现频繁的换入换出,从而导致table_id增长比较快。

    

   查询了下线上mysql的一些参数和运行数据:

   

1.  查询table def cache

mysql> show variables like 'table%';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| table_definition_cache | 2048  |
| table_open_cache       | 2048  |
+------------------------+-------+


2.  查询当前使用的table def

mysql> show status like 'open%';
+--------------------------+----------+
| Variable_name            | Value    |
+--------------------------+----------+
| Open_files               | 14       |
| Open_streams             | 0        |
| Open_table_definitions   | 2048     |
| Open_tables              | 2048     |
| Opened_files             | 47198363 |
| Opened_table_definitions | 1183     |
| Opened_tables            | 1342     |
+--------------------------+----------+


所以基本上table def cache一直是处于满的状态,统计了下表,因为存在分库分表,所以一个数据库实例上的表超过了6000张。

cache 2048 ,  table 6000张,势必会出现频繁的换入换出,这也就难怪table_id频繁增长了

解决

1.  tablemap cache策略以事务为单位进行局部cache,事务结束后清空tablemap cache,所以tableId的频繁增长不再会受到影响

2.  表结构的cache独立出来,以schmea + table name做为cache key,总的cache数也就会<=数据库中的表的总数

可以做的一个优化:

1.  针对分库分表的业务,基本上字段定义都是一样的,从内存dump的分析来看,一张表50个字段,表结构的定义大小大概为6kb,大部分都几种在column name(文本),其实可以利用String.intern()进行共享内存,1024张的分表可以只用一份表结构定义,内存可以从6MB ->  6KB. 

针对table_id增长的问题,这里还有一个其他风险:淘宝物流MySQL slave数据丢失详细原因

--转自 北京联动北方科技有限公司




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论