mysql TableMap id递增问题
背景
? ?這兩天在線上運行的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
2. ?查詢當前使用的table def
所以基本上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數據丟失詳細原因
總結
以上是生活随笔為你收集整理的mysql TableMap id递增问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】tcp链接的状态
- 下一篇: 解决Sublime包管理package