MySQL數據庫服務器逐漸變慢 該如何分析與解決

http://www.mysqlops.com/2011/12/03/mysql-question.html

第一步 檢查系統的狀態

通過操作系統的一些工具檢查系統的狀態,比如CPU、內存、交換、磁盤的利用率,根據經驗或與系統正常時的狀態相比對,有時系統表面上看起來看空閒,這也可能不是一個正常的狀態,因爲cpu可能正等待IO的完成。除此之外,還應觀注那些佔用系統資源(cpu、內存)的進程。

1.1 使用sar來檢查操作系統是否存在IO問題

#sar -u 2 10 — 即每隔2秒檢察一次,共執行20次。
結果示例:
注:在redhat下,%system就是所謂的%wio。
Linux 2.4.21-20.ELsmp (YY075) 05/19/2005
10:36:07 AM CPU %user %nice %system %idle
10:36:09 AM all 0.00 0.00 0.13 99.87
10:36:11 AM all 0.00 0.00 0.00 100.00
10:36:13 AM all 0.25 0.00 0.25 99.49
10:36:15 AM all 0.13 0.00 0.13 99.75
10:36:17 AM all 0.00 0.00 0.00 100.00
其中:
Ø %usr指的是用戶進程使用的cpu資源的百分比;
Ø %sys指的是系統資源使用cpu資源的百分比;
Ø %wio指的是等待io完成的百分比,這是值得觀注的一項;
Ø %idle即空閒的百分比。
如果wio列的值很大,如在35%以上,說明系統的IO存在瓶頸,CPU花費了很大的時間去等待I/O的完成。Idle很小說明系統CPU很忙。像以上的示例,可以看到wio平均值爲11,說明I/O沒什麼特別的問題,而idle值爲零,說明cpu已經滿負荷運行了。

1.2 使用vmstat監控內存 cpu資源

[root@mysql1 ~]# vmstat

procs ———–memory———- —swap– —–io—- –system– —–cpu——

r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

0  0     72  25428  54712 672264    0    0    14    43   53   59  1  1 98  0  0

 

vmstat 的輸出那些信息值得關注?

io bo: 磁盤寫的數據量稍大,如果是大文件的寫,10M以內基本不用擔心,如果是小文件寫2M以內基本正常

 

1.2.1 CPU問題
下面幾列需要被察看,以確定cpu是否有問題
Processes in the run queue (procs r)
User time (cpu us)
System time (cpu sy)
Idle time (cpu id)

問題情況:
1.) 如果processes in run queue (procs r)的數量遠大於系統中cpu的數量,將會使系統便慢。
2.) 如果這個數量是cpu的4倍的話,說明系統正面臨cpu能力短缺,這將使系統運行速度大幅度降低
3.) 如果cpu的idle時間經常爲0的話,或者系統佔用時間(cpu sy)是用戶佔用時間(cpu us)兩輩的話,系統面臨缺少cpu資源
解決方案 :
解決這些情況,涉及到調整應用程序,使其能更有效的使用cpu,同時增加cpu的能力或數量

1.2.2內存問題
主要查看頁導入的數值(swap中的si),如果該值比較大就要考慮內存,大概方法如下:
1).最簡單的,加大RAM
2).減少RAM的需求

1.3磁盤IO問題

處理方式:做raid10提高性能

1.4網絡問題

telnet一下MySQL對外開放的端口,如果不通的話,看看防火牆是否正確設置了。另外,看看MySQL是不是開啓了skip-networking的選項,如果開啓請關閉。

第二步 檢查mysql參數

2.1 幾個不被注意的mysql參數

2.1.1 max_connect_errors

max_connect_errors默認值爲10,如果受信帳號錯誤連接次數達到10則自動堵塞,需要flush hosts來解除。如果你得到象這樣的一個錯誤:

Host ’hostname’ is blocked because of many connection errors.

Unblock with ’mysqladmin flush-hosts’

這意味着,mysqld已經得到了大量(max_connect_errors)的主機’hostname’的在中途被中斷了的連接請求。在max_connect_errors次失敗請求後,mysqld認定出錯了(象來字一個黑客的攻擊),並且阻止該站點進一步的連接,直到某人執行命令mysqladmin flush-hosts。

內網連接的話,建議設置在10000以上,已避免堵塞,並定期flush hosts。

2.1.2 connect_timeout

指定MySQL服務等待應答一個連接報文的最大秒數,超出該時間,MySQL向客戶端返回 bad handshake。默認值是5秒,在內網高併發環境中建議設置到10-15秒,以便避免bad hand shake。建議同時關注thread_cache_size並設置thread_cache_size爲非0值,大小具體調整。

2.1.3 skip-name-resolve

skip-name-resolve能大大加快用戶獲得連接的速度,特別是在網絡情況較差的情況下。MySQL在收到連接請求的時候,會根據請求包中獲得的ip來反向追查請求者的主機名。然後再根據返回的主機名又一次去獲取ip。如果兩次獲得的ip相同,那麼連接就成功建立了。在DNS不穩定或者局域網內主機過多的情況下,一次成功的連接將會耗費很多不必要的時間。假如MySQL服務器的ip地址是廣域網的,最好不要設置skip-name-resolve。

2.1.4 slave-net-timeout=seconds

參數含義:當slave從主數據庫讀取log數據失敗後,等待多久重新建立連接並獲取數據。默認值是3600秒,如果需要保證同步性,如此NC的參數請極力控制在10秒以下。

2.1.5 master-connect-retry

參數含義:當重新建立主從連接時,如果連接建立失敗,間隔多久後重試。默認是60秒,請按照合理的情況去設置參數。

 

第三步 檢查mysql 相關狀態值

3.1關注連接數

如果連接數達到了最大連接數,那不管 有多少資源,用戶都會阻塞在外面。

修改mysql最大連接數:

打開my.ini,修改max_connections=100(默認爲100)。

請根據硬件情況調整到合適的大小,一般經驗值可設爲3000。Windows服務器大概支持量爲1500-1800個連接,linux服務器可以支持到8000個左右。

請將max_user_connections設0——–這個0代表不限制單用戶的最大連接數,其最大連接值可以等於max_connections值。

mysql> show global status like ‘Max_used_connections’;

檢查下最大的過往使用連接數,這個值在max_connections的85%左右是比較合適的,如果過高則是max_connections過少或者系統負荷過高了。

 

3.1.1 mysqladmin -uroot status

[root@mysql1 ~]# mysqladmin -uroot status

Uptime: 1742276  Threads: 2  Questions: 2538  Slow queries: 0  Opens: 145  Flush tables: 1  Open tables: 23  Queries per second avg: 0.1

3.1.2 show full processlist

1.顯示所有進程

mysql> show full processlist;

+—–+——+———–+——+———+——+——-+———————–+

| Id  | User | Host      | db   | Command | Time | State | Info                  |

+—–+——+———–+——+———+——+——-+———————–+

| 629 | root | localhost | NULL | Query   |    0 | NULL  | show full processlist |

| 633 | root | localhost | NULL | Sleep   |   11 |       | NULL                  |

+—–+——+———–+——+———+——+——-+———————–+

2 rows in set (0.00 sec)

 

2.如果正在運行的語句太多,運行時間太長,表示MySQL效率有問題。必要的時候可以將對應的進程kill掉。

殺死休眠的進程kill ID號

mysql> kill 633;

Query OK, 0 rows affected (0.00 sec)

 

3.關注TIME參數,看看正在運行的用戶進程有多少是長時間佔用的,具體分析下。

3.1.3使用mysqlreport關注Connections,Threads

__ Connections _________________________________________________________

Max used            3 of  200      %Max:   1.50

Total          30.16k     0.7/s

。。。。。。

__ Threads _____________________________________________________________

Running             1 of    2

Cached              1 of  300      %Hit:  99.99

Created             3     0.0/s

Slow                0       0/s

3.2關注下系統鎖情況

3.2.1 mysql> show status like ‘%lock%’;

+——————————-+———+

| Variable_name                 | Value   |

+——————————-+———+

| Com_lock_tables               | 0       |

| Com_unlock_tables             | 0       |

| Innodb_row_lock_current_waits | 0       |

| Innodb_row_lock_time          | 0       |

| Innodb_row_lock_time_avg      | 0       |

| Innodb_row_lock_time_max      | 0       |

| Innodb_row_lock_waits         | 0       |

| Table_locks_immediate         | 2667760 |

| Table_locks_waited            | 0       |

   

3.2.2使用mysqlreport關注Table Locks,InnoDB Lock

__ Questions ___________________________________________________________

Total           3.38M    81.4/s

DMS           2.88M    69.3/s  %Total:  85.11

QC Hits     382.70k     9.2/s           11.32

Com_         90.50k     2.2/s            2.68

COM_QUIT     30.15k     0.7/s            0.89

+Unknown         18     0.0/s            0.00

Slow 1 s           92     0.0/s            0.00  %DMS:   0.00  Log: OFF

。。。。。。

__ Table Locks _________________________________________________________

Waited              0       0/s  %Total:   0.00

Immediate       2.67M    64.2/s

。。。。。。

__ InnoDB Lock _________________________________________________________

Waits               0       0/s

Current             0

Time acquiring

Total             0 ms

Average           0 ms

Max               0 ms

。。。。。。

如果wait過多,平均時間過長,那就是查詢設計的有問題,仔細關注下超長時間的查詢,並打開slow_query_log。

3.3 關注慢查詢(slow query)日誌

日誌必然會拖慢系統速度,特別是CPU資源,所以如果CPU資源充分,可以一直打開,如果不充足,那就在需要調整的時候,或者在replication從服務器上打開(針對select)

mysql> show variables like ‘%slow%’;

+———————+—————————————-+

| Variable_name       | Value                                  |

+———————+—————————————-+

| log_slow_queries    | OFF                                    |

| slow_launch_time    | 2                                      |

| slow_query_log      | OFF                                    |

| slow_query_log_file | /data0/mysql/3306/data/mysql1-slow.log |

+———————+—————————————-+

4 rows in set (0.00 sec)

 

mysql> set  GLOBAL slow_query_log=on;

Query OK, 0 rows affected (0.00 sec)

3.3.1關注慢查詢涉及的表的相關狀態

1.       表內記錄數。儘量控制在500萬行以內(有索引),建議控制在200萬行

2.       表內索引的使用。

3.       表如果update,delete,insert頻繁,可以考慮optimize table優化下文件存放,索引,存儲空間。

4.       表內update,insert,delete查詢的鎖定時間。

5.       select for update如果條件字段無索引的話,會引起的是鎖全表而不是行鎖,請關注。

6.       如果查詢包括GROUP BY但你想要避免排序結果的消耗,你可以指定ORDER BY NULL禁止排序。

3.3.2定期分析表

ANALYZE TABLE

語法:

ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] …

本語句用於分析和存儲表的關鍵字分佈。在分析期間,使用一個讀取鎖定對錶進行鎖定。這對於MyISAM, BDB和InnoDB表有作用。對於MyISAM表,本語句與使用myisamchk -a相當。

CHECK TABLE

語法:

CHECK TABLE tbl_name [, tbl_name] … [option] …

option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}

檢查一個或多個表是否有錯誤。CHECK TABLE對MyISAM和InnoDB表有作用。對於MyISAM表,關鍵字統計數據被更新。

CHECK TABLE也可以檢查視圖是否有錯誤,比如在視圖定義中被引用的表已不存在。

CHECKSUM TABLE

語法:

CHECKSUM TABLE tbl_name [, tbl_name] … [ QUICK | EXTENDED ]

報告一個表校驗和。

3.3.3使用optimize table

OPTIMIZE TABLE

語法:

OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] …

如果已經刪除了表的一大部分,或者如果您已經對含有可變長度行的表(含有VARCHAR, BLOB或TEXT列的表)進行了很多更改,則應使用OPTIMIZE TABLE。被刪除的記錄被保持在鏈接清單中,後續的INSERT操作會重新使用舊的記錄位置。您可以使用OPTIMIZE TABLE來重新利用未使用的空間,並整理數據文件的碎片。

OPTIMIZE TABLE只對MyISAM, BDB和InnoDB表起作用。


發佈了5 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章