前幾天業務線發現一例MySQL資料庫記憶體增長異常案例,現象如下:

資料庫版本:Percona MySQL 5.0.67
資料量:670M+
記憶體大小:16G
Innodb Buffer Pool Size:4G
其它回話記憶體分配並不大,基本在100M以內,並且連接數非常少
伺服器負載不高,開啟Binlog,資料庫和程式都已經進行過遷移,問題仍然存在。通過top命令查看MySQL佔用記憶體一直在增長,且開始使用Swap。

 

分析排除過程:
1.懷疑到的是InnoDB記憶體佔用,使用show engine innodb status查看,發現Free Buffer占很大部分,因此可以判斷分配給Innodb引擎的記憶體夠用
2.查看回話,回話數基本在3~4個,且回話分配的記憶體大小與現在MySQL佔用的回話總和相差很大,因此也不會是回話的問題
3.程式、資料庫軟體問題。已經遷移過兩次,版本與外網一致,問題依舊,因此也排除了這個問題
4.MySQL重啟後記憶體釋放,因此問題還是在MySQL身上,根據網上說的Flush Tables的做法發現無效,所以也不是打開的表數量過大的問題導致。

 

就在臨時維護前1小時,網上查找案例時,有人說記憶體表配置不當也有可能導致記憶體異常,但因為天龍沒有用到Memory引擎,因此沒太在意,但已經山窮水盡,也不知道該做什麼,就查了下資料庫中Innodb以外的表,主要集中在mysql庫及information_schema庫:
+——————–+—————————————+——–+
| TABLE_SCHEMA | TABLE_NAME | ENGINE |
+——————–+—————————————+——–+
| information_schema | CHARACTER_SETS | MEMORY |
| information_schema | CLIENT_STATISTICS | MEMORY |
| information_schema | COLLATIONS | MEMORY |
| information_schema | COLLATION_CHARACTER_SET_APPLICABILITY | MEMORY |
| information_schema | COLUMNS | MyISAM |
……
| mysql | help_topic | MyISAM |
| mysql | time_zone | MyISAM |
| mysql | time_zone_leap_second | MyISAM |
| mysql | time_zone_name | MyISAM |
| mysql | time_zone_transition | MyISAM |
| mysql | time_zone_transition_type | MyISAM |
| mysql | user | MyISAM |
+——————–+—————————————+——–+
因為MyISAM表不多,而且表都不大,記憶體分配也沒有問題,所以我大概過了一遍,剩下的就是MEMORY 表了。
單獨對這些表進行查看,最終發現CLIENT_STATISTICS表非常異常,原因是作為記憶體表查詢速度非常慢,,並且會報錯,在/tmp/下的一個暫存檔案需要修復,因此到/tmp目錄下進行查看,基本就定位到問題了:匯出的臨時表約為7~8G!
查看表資料基本不可能,因此在維護時,重啟了資料庫,並且查看了裡面的資料,發現資料增長非常快,裡面記錄的都是用戶端的連接記錄,比較特別的就是主機名稱顯示不全。因此我們選擇將主機名稱改成IP的形式,用於定位出問題的伺服器(當時還在懷疑是程式連接中斷導致記錄數增長)。但修改完後發現問題消失了,該台伺服器與其他伺服器區別,問題表的資料量也正常了,因此我們定位問題到了主機名稱上,我進行了一下實驗:

 

現在有245、246兩台機器:
246是用戶端、245是伺服器端
(root:245:Thu Apr 24 16:37:28 2014)[information_schema]> select count(*) from CLIENT_STATISTICS;
+———-+
| count(*) |
+———-+
| 2 |
+———-+
1 row in set (0.00 sec)
可以看到表裡面的資料是2條

 

[dbatlbb@ ~]$ mysql -h 245 -uwuwl_test -p
mysql: Can’t create/write to file ‘/home/mysql/query.log’ (Errcode: 13)
Error logging to file ‘/home/mysql/query.log’
Logging to file ‘/home/dbatlbb/mysql/query.log’
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 556
Server version: 5.0.67-percona-highperf-log Source distribution

 

Type ‘help;’ or ‘\h’ for help. Type ‘\c’ to clear the buffer.

 

(wuwl_test:${HOSTNAME}:Thu Apr 24 16:39:19 2014)[(none)]> show processlist;
+—–+———–+———————————+——+———+——+——-+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—–+———–+———————————+——+———+——+——-+——————+
| 556 | wuwl_test | gs_438_friuha_fgesihs_fsd:50768 | Null | Query | 0 | Null | show processlist |
+—–+———–+———————————+——+———+——+——-+——————+
1 row in set (0.00 sec)
連接了一下,並進行了一次查詢操作
(root:NJ-245:Thu Apr 24 16:38:38 2014)[information_schema]> select count(*) from CLIENT_STATISTICS;
+———-+
| count(*) |
+———-+
| 5 |
+———-+
1 row in set (0.01 sec)
發現資料有增長,再次進行幾次查詢,發現每次查詢都會有增長,這個正常現象麼?我修改了下主機名稱進行了重新查詢,發現表資料不再增長。
修改方法:主機名稱需要小於16位元組。
目前在5.5和5.6版本上進行了測試,發現這個表資料為空,因此這個問題可能是在5.0版本上面的一個BUG。

 

總結:
本次問題現象主要是:記憶體異常被MySQL佔用不釋放並持續上漲,更換過程式和資料庫伺服器仍沒有效果,伺服器資料量很小,Innodb Buffer空閒很大。
問題原因:由於資料庫自身的統計資料表information_schema.CLIENT_STATISTICS 資料量過大導致記憶體佔用,CLIENT_STATISTICS是一張記憶體表。
問題處理方法:由於CLIENT_STATISTICS表裡面的Host列是16個位元組的,因此如果主機名稱過長,會導致用戶端每一次的操作都會在表裡面新增一條資料,無論操作是否成功。因此只需要修改連接的主機名稱不要超過16位就不會導致記憶體佔用不釋放的問題。
思考:修改了預設的東西,需要在小部分伺服器上進行測試,並詳細記錄修改後的異常,用於對比不同伺服器之間的差別。

 

延伸:
CLIENT_STATISTICS 用於統計用戶端連接,目前5.5、5.6以及Maria已經將client欄位升級為64個位元組,且該統計功能預設關閉,所以如果大家有統計需要,一定要記得主機名稱不能大於64個位元組!

 

HTTPs://mariadb.com/kb/en/information-schema-client_statistics-table/

來自

http://www.bkjia.com/sjkqy/761163.html

arrow
arrow
    全站熱搜

    戮克 發表在 痞客邦 留言(0) 人氣()