Mysql 調優

調優思路簡介

• 0.硬件優化
• 1.數據庫設計與規劃–以後再修改很麻煩,估計數據量,使用什麼存儲引擎
• 2.數據的應用–怎樣取數據,sql 語句的優化
• 3.磁盤 io 優化
• 4.操作系統的優化–內核、tcp 連接數量
• 5.mysql 服務優化–內存的使用,磁盤的使用
• 6.my.cnf 內參數的優化:

硬件優化

CPU—— 64 位、高主頻、高緩存,高並行處理能力
內存——大內存、主頻高,儘量不要用 SWAP
硬盤——15000轉、RAID5、raid10 。 SSD
網絡——標配的千兆網卡,10G網卡,bond0,msyql服務器儘可能和使用它的web服務器在同一局域網內,儘量避免諸如防火牆策略等不必要的開銷。

數據庫設計與規劃(架構上的優化)

縱向拆解: 專機專用

例:現在公司一臺服務器同時負責 web、ftp、數據庫等多個角色。 R720 dell 內存 :768G
縱向拆解後就是:數據庫服務器專機專用,避免額外的服務可能導致的性能下降和不穩定性。
在這裏插入圖片描述

橫向拆解:

主從同步、負載均衡、高可用性集羣,當單個 mysql 數據庫無法滿足日益增加的需求時,可以考慮在數據庫這個邏輯層面增加多臺服務器,以達到穩定、高效的效果。

查詢優化

a>建表時表結構要合理,每個表不宜過大;在任何情況下均應使用最精確的類型。例如,如果ID列用int是一個好主意,而用text類型則是個蠢辦法;TIME列酌情使用DATE或者DATETIME。
b>索引,建立合適的索引。
c>查詢時儘量減少邏輯運算(與運算、或運算、大於小於某值的運算);
d>減少不當的查詢語句,不要查詢應用中不需要的列,比如說select * from 等操作。
e>減小事務包的大小;
f>將多個小的查詢適當合併成一個大的查詢,減少每次建立/關閉查詢時的開銷;
g>將某些過於複雜的查詢拆解成多個小查詢,和上一條恰好相反
h>建立和優化存儲過程來代替大量的外部程序交互。

磁盤 io 規劃,io相關的技術

raid 技術:raid0或raid10
SSD:15000轉、RAID5、raid10、SSD
swap 分區:最好使用 raid0 或 SSD
磁盤分區:將數據庫目錄放到一個分區上或一個磁盤上的物理分區. 存儲數據的硬盤或分區和系統所在的硬盤分開。
在這裏插入圖片描述
設置主從時,由於binlog日誌頻繁記錄操作,開銷非常大,需要把binlog日誌放到其它硬盤分區上:

#vim /etc/my.cnf
[mysqld] 
datadir=/data/  #放在獨立的硬盤上SSD
socket=/var/lib/mysql/mysql.sock 
user=mysql 
# Disabling symbolic-links is recommended to prevent assorted security risks 
symbolic-links=0 #在原配置文件中,添加以下內容: 
log-bin=/data/mysqllog #啓用二進制日誌,默認存在/var/lib/mysql 下面 
server-id=1 #本機數據庫ID 標示。 
binlog-do-db=db #可以被從服務器複製的庫。二進制需要同步的數據庫名

操作系統的優化

網卡 bonding 技術
設置tcp 連接數量限制,優化系統打開文件的最大限制。
使用64位操作系統,64位系統可以分給單個進程更多的內存。
禁用不必要啓動的服務
文件系統調優,給數據倉庫一個單獨的文件系統,推薦使用XFS,一般效率更高、更可靠。
最小化原則:
1.安裝系統最小化
2.開啓程序服務最小化原則
3.操作最小化原則
4.登錄最小化原則
5.權限最小化

mysql 服務優化(數據庫服務的優化)

保持每個表都不要太大,可以對大表做橫切和縱切:比如說我要取得某 ID 的 lastlogin, 完全可以做一張只有“ID和 “lastlog”的小表,而非幾十、幾百列數據的並排大表。
另外對一個有 1000 萬條記錄的表做更新比對 10 個 100 萬記錄的表做更新一般來的要慢。

存儲引擎:

myisam 引擎,表級鎖,表級鎖開銷小,影響範圍大,適合讀多寫少的表,不支持事務。 表鎖定不存在死鎖 (也有例外)
innodb 引擎,行級鎖,鎖定行的開銷要比鎖定全表要大。影響範圍小,適合寫操作比較頻繁的數據表。行級鎖可能存在死鎖。
MySQL的鎖機制比較簡單,其最顯著的特點是不同的存儲引擎支持不同的鎖機制。

死鎖排查

開啓後會將所有的死鎖記錄到error_log中 錯誤日誌在my.cnf配置爲log-error=/var/log/mysqld.log

innodb_print_all_deadlocks = 1
innodb_sort_buffer_size = 16M

查看數據庫服務的狀態,登錄mysql

mysql> show status; 看系統的狀態 
mysql> show engine innodb status \G #顯示 InnoDB 存儲引擎的狀態 \G以行的形式展示
mysql> show variables; 看變量,在 my.cnf 配置文件裏定義的變量值

查看警告信息

mysql> show warnings; 查看最近一個 sql 語句產生的錯誤警告, 看其他的錯誤信息,需要看日誌/var/log/mysqld.log。

例:查看警告信息

mysql> adadfs; #隨便輸入一些內容,回車。將看到以下一些錯誤信息 
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'adadfs' at line 1 
mysql> show warnings; 
mysql> show processlist ; #顯示mysql系統中正在運行的所有線程。 可以看到每個客戶端正在執行的命令 
#本語句TCP/IP連接的主機名稱(採用host_name:client_port格式),以方便地判定哪個客戶端正在做什麼。

在這裏插入圖片描述

啓用 mysql 慢查詢

分析 sql 語句,找到影響效率的 SQL

vim /etc/my.cnf 
[mysqld] 
slow_query_log = 1  #開啓慢查詢日誌
slow-query-log-file=/var/lib/mysql/slow.log  #這個路徑對 mysql 用戶具有可寫權限 
long_query_time=5  #查詢超過 5 秒鐘的語句記錄下來
log-queries-not-using-indexes =1  #沒有使用索引的查詢

這三個設置一起使用,可以記錄執行時間超過5 秒和沒有使用索引的查詢。請注意有關log-queries-not-using-indexes的警告。慢速查詢日誌都保存在/var/lib/mysql/slow.log。
查看:
在這裏插入圖片描述

my.cnf 內參數的優化

優化總原則:給 mysql 的資源太少,則 mysql 施展不開:給 mysql 的資源太多,可能會拖累整個 OS。
40%資源給OS, 60%-70% 給mysql (內存和CPU)

對查詢進行緩存

大多數LAMP應用都嚴重依賴於數據庫查詢,查詢的大致過程如下:
PHP發出查詢請求->數據庫收到指令對查詢語句進行分析->確定如何查詢->從磁盤中加載信息->返回結果
如果反覆查詢,就反覆執行這些。MySQL 有一個特性稱爲查詢緩存,他可以將查詢的結果保存在內存中,在很多情況下,這會極大地提高性能。不過,問題是查詢緩存在默認情況下是禁用的。

啓動查詢緩存

vim /etc/my.cnf 
[mysqld] #在此字段中添加 
query_cache_size = 32M 
Systemctl restart mysqld #重啓服務
查看:查詢緩存 

在這裏插入圖片描述
解釋如下:
變量名 說明

  1. Qcache_free_blocks #緩存中相鄰內存塊的個數。數目大說明可能有碎片。
    如果數目比較大,可以執行:
    mysql> flush query cache;
    #對緩存中的碎片進行整理,從而得到一個空閒塊。
  2. Qcache_free_memory #緩存中的空閒內存大小
  3. Qcache_hits #每次查詢在緩存中命中時就增大。
  4. Qcache_inserts #每次插入一個查詢時就增大。即沒有從緩存中找到數據
  5. Qcache_lowmem_prunes #因內存不足刪除緩存次數,緩存出現內存不足並且必須要進行清理,以便爲更多查詢提供空間的次數。返個數字最好長時間來看;如果返個數字在不斷增長,就表示可能碎片非常嚴重,或者緩存內存很少。
    如果Qcache_free_blocks比較大,說明碎片嚴重。 如果 free_memory 很小,說明緩存不夠用了。
  6. Qcache_not_cached # 沒有進行緩存的查詢的數量,通常是這些查詢未被緩存或其類型不允許被緩存
  7. Qcache_queries_in_cache # 在當前緩存的查詢(和響應)的數量。
  8. Qcache_total_blocks #緩存中塊的數量。

例:使用mysql查詢緩存

cat /etc/my.cnf 
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
query_cache_size = 32m	#至少4M以存儲數據結構,可擴展。整體100G,若此服務器只運行mysql服務器。70-80G給mysql
Systemctl restart mysqld;#重啓服務
mysql> create database aa;
mysql> use aa;
mysql> create table test3 (id int, name varchar(255)) ;
mysql> insert into test3 values (1,'aaaa'), (2,'aaaa');
mysql> select * from test3;
mysql> show status like "qcache%";
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 33535112 |
| Qcache_hits             | 0        |#沒有命中
| Qcache_inserts          | 1 |#第一次插入一個語句
| Qcache_lowmem_prunes    | 0        |
| Qcache_not_cached       | 3        |
| Qcache_queries_in_cache | 1        |
| Qcache_total_blocks     | 4        |

再查詢:

mysql> select * from test3;
mysql> show status like "qcache%";
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 33535112 |
| Qcache_hits             | 1|#第二次查詢時,就命中了。
| Qcache_inserts          | 1        |

Qcache_hits/(Qcache_inserts+ Qcache_hits) 命中率

經過多次select,命中的次數也會增加

mysql> show status like 'qcache%';  
+-------------------------+----------+
| Variable_name           | Value    |
+-------------------------+----------+
| Qcache_free_blocks      | 1        |
| Qcache_free_memory      | 33535344 |
| Qcache_hits             | 3        |#第四次查詢時,就命中3次。
| Qcache_inserts          | 1        |

強制限制mysql 資源設置

您可以在mysqld中強制一些限制來確保系統負載不會導致資源耗盡的情況出現

vim /etc/my.cnf 
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
query_cache_size = 32M 
max_connections=500  上限是看硬件配置
wait_timeout=10 
max_connect_errors = 100

第一行:最大連接數,在服務器沒有崩潰之前確保只建立服務允許數目的連接。
該參數設置過小的最明顯特徵是出現“Too many connections”錯誤;
第二行:mysqld將終止等待時間(空閒時間)超過10秒的連接。在LAMP應用程序中,連接數據庫的時間通常就是Web 服務器處理請求所花費的時間。有時候如果負載過重,連接會掛起,並且會佔用連接表空間。如果有多個交互用戶使用了到數據庫的持久連接,那麼應該將這個值設低一點。
第三行:如果一個主機在連接到服務器時有問題,並重試很多次後放棄,那麼這個主機就會被鎖定,直到執行:
mysql> FLUSH HOSTS;
Query OK, 0 rows affected (0.00 sec)
之後才能運行。默認情況下,10 次失敗就足以導致鎖定了。將這個值修改爲100 會給服務器足夠的時間來從問題中恢復。如果重試100 次都無法建立連接,那麼使用再高的值也不會有太多幫助,可能它根本就無法連接。

例:

cat /etc/my.cnf 

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
query_cache_size = 32M 
max_connections=500  
wait_timeout=10  
max_connect_errors = 100
service mysqld restart

驗證:

mysql> show status like 'max_used_connections';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Max_used_connections | 1  |#當前有一個mysql
+----------------------+-------+
1 row in set (0.00 sec)
再另一個客戶端打開一個mysql連接,執行一下查詢,可以看到有兩個:
mysql> show status like 'max_used_connections';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| Max_used_connections | 2  |

小計:
mysql有超過100個可以調節的設置,要記住那麼多基本是不可能的,但是幸運的是你只需要記住很少一部分你就可以基本滿足你的需求了,我們還可以通過“SHOW STATUS”命令來查看mysql是否按照我們的期望在運行。

表高速緩存

數據庫中的每個表存儲在一個文件中,要讀取文件的內容,你必須先打開文件,然後再讀取。爲了加快從文件中讀取數據的過程,mysqld 對這些打開文件進行了緩存,其最大數目由 /etc/my.cnf中的 table_cache 指定

例如:

cat /etc/my.cnf 
[mysqld] 
datadir=/var/lib/mysql 
…… 
table_open_cache=23  #緩存23個表 

mysql>  show global status like 'open%_tables';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Open_tables   | 1     |
| Opened_tables | 114   |
+---------------+-------+ 

Open_tables 表示打開表的數量,Opened_tables表示打開過的表數量,如果Opened_tables數量過大,說明配置中 table_cache(5.1.3之後這個值叫做table_open_cache)值可能太小.
table_cache 的值在 2G 內存以下的機器中的值默認從 256 到 512個。
對於有 1G 內存的機器,推薦值是 128-256。

關鍵字緩衝區

key_buffer_size指定索引緩衝區的大小,它決定索引處理的速度,尤其是索引讀的速度。
例:關鍵字緩存 , 緩存來緩存索引

cat /etc/my.cnf 
[mysqld]
datadir=/var/lib/mysql
……
key_buffer_size=512M

#只跑一個mysql服務。結合所有緩存,mysql整體使用的緩存可以使用物理內存的80%

systemctl restart mysqld
mysql> show status like '%key_read%';  #查看:
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Key_read_requests | 0     |
| Key_reads         | 0     |
+-------------------+-------+

Key_reads 代表命中磁盤的請求個數,Key_read_requests 是總數, 命中磁盤的讀請求數除以讀請求總數就是不中比率。
命中率:(1-(Key_reads / Key_read_requests ) )*100
如果每 1,000 個請求中命中磁盤的數目超過 1 個,就應該考慮增大關鍵字緩衝區了。

mysql> create database mk;
mysql> use mk;
mysql> create table t3 (id int,name varchar(24));
mysql> insert into t3 values (1,'aaaaa'),(2,'aaaaa'),(3,'aaaaa');
mysql> create index idx_name on t3(name);
mysql> show status like '%key_read%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Key_read_requests | 2|
| Key_reads         | 0     |
+-------------------+-------+
mysql> select name from t3;

mysql> show status like '%key_read%';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| Key_read_requests | 4|
| Key_reads         | 1  |
+-------------------+-------+

總結

1、看機器配置,指三大件:cpu、內存、硬盤
2、看mysql配置參數
3、查看mysql行狀態
4、查看mysql的慢查詢
依次解決了以上問題之後,再來查找程序方面的問題

#索引緩存,根據內存大小而定,如果是獨立的db服務器,可以設置高達80%的內存總量
key_buffer_size= 512M

#打開表緩存總個數,可以避免頻繁的打開數據表產生的開銷
table_open_cache = 20
query_cache_size = 128M
max_connections=10000# 最大連接數 內存

#設置超時時間,能避免長連接
wait_timeout=60

#記錄慢查詢,然後對慢查詢一一優化單位:秒
slow-queries- log-file= /var/lib/mysql/slow.log
long_query_time = 5

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章