摘要
mysql安裝之后並不是默認參數就能滿足生產系統的需要,需要根據業務調整很多的參數。
參數說明
硬件 16 CPU 32G Memory
# For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html [mysql] default-character-set = utf8mb4 [mysqld] character-set-client-handshake = FALSE character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect='SET NAMES utf8mb4' skip_host_cache skip-name-resolve=1 ###NEW#### expire_logs_days=7 back_log=300 max_connections=8000 max_connect_errors=30 #table_cache=4096 open_files_limit=10240 #thread_concurrency=64 max_allowed_packet=100000000 net_buffer_length=100000 interactive_timeout=300 wait_timeout=300 thread_cache_size=100 slow_query_log=1 long_query_time=5 sort_buffer_size=16M read_buffer_size=16M read_rnd_buffer_size=32M join_buffer_size=128M tmp_table_size=64M table_open_cache=5000 key_buffer_size=400M query_cache_size=128M thread_stack=512K innodb_buffer_pool_size=24G #innodb_additional_mem_pool_size=20M #innodb_file_io_threads=4 innodb_thread_concurrency=16 innodb_log_buffer_size=16M innodb_log_file_size=512M innodb_log_files_in_group=3 innodb_lock_wait_timeout=120 ###NEW#### # # Remove leading # and set to the amount of RAM for the most important data # cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%. # innodb_buffer_pool_size = 128M # # Remove leading # to turn on a very important data integrity option: logging # changes to the binary log between backups. # log_bin # # Remove leading # to set options mainly useful for reporting servers. # The server defaults are faster for transactions and fast SELECTs. # Adjust sizes as needed, experiment to find the optimal values. # join_buffer_size = 128M # sort_buffer_size = 2M # read_rnd_buffer_size = 2M datadir=/opt/data/mysql socket=/var/lib/mysql/mysql.sock # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 log-error=/var/log/mysqld.log pid-file=/var/run/mysqld/mysqld.pid lower_case_table_names =1 # master log-bin=mysql-bin server-id=2
back_log
該值指出在MySQL暫時停止回答新請求之前的短時間內多少個請求可以被存在堆棧中。也就是說,如果MySql的連接數據達到max_connections時,新來的請求將會被存在堆棧中,以等待某一連接釋放資源,該堆棧的數量即back_log,如果等待連接的數量超過back_log,將不被授予連接資源。將會報:unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待連接進程時.
back_log值不能超過TCP/IP連接的偵聽隊列的大小。若超過則無效,查看當前系統的TCP/IP連接的偵聽隊列的大小命令:cat /proc/sys/net/ipv4/tcp_max_syn_backlog目前系統為1024。對於Linux系統推薦設置為小於512的整數。
wait-timeout
MySQL默認的wait-timeout 值為8個小時,可以通過命令show variables like 'wait_timeout'查看結果值;。
設置這個值是非常有意義的,比如你的網站有大量的MySQL鏈接請求(每個MySQL連接都是要內存資源開銷的 ),由於你的程序的原因有大量的連接請求空閑啥事也不干,白白占用內存資源,或者導致MySQL超過最大連接數從來無法新建連接導致“Too many connections”的錯誤。在設置之前你可以查看一下你的MYSQL的狀態(可用show processlist),如果經常發現MYSQL中有大量的Sleep進程,則需要 修改wait-timeout值了。
interactive_timeout:服務器關閉交互式連接前等待活動的秒數。交互式客戶端定義為在mysql_real_connect()中使用CLIENT_INTERACTIVE選項的客戶端。
wait_timeout:服務器關閉非交互連接之前等待活動的秒數。在線程啟動時,根據全局wait_timeout值或全局 interactive_timeout值初始化會話wait_timeout值,取決於客戶端類型(由mysql_real_connect()的連接選項CLIENT_INTERACTIVE定義).
這兩個參數必須配合使用。否則單獨設置wait_timeout無效。
max_connections
指MySql的最大連接數,如果服務器的並發連接請求量比較大,建議調高此值,以增加並行連接數量,當然這建立在機器能支撐的情況下,因為如果連接數越多,介於MySql會為每個連接提供連接緩沖區,就會開銷越多的內存,所以要適當調整該值,不能盲目提高設值。可以過'conn%'通配符查看當前狀態的連接數量,以定奪該值的大小。
MySQL服務器允許的最大連接數16384;
查看系統當前最大連接數:
show variables like 'max_connections';
max_user_connections
是指每個數據庫用戶的最大連接
針對某一個賬號的所有客戶端並行連接到MYSQL服務的最大並行連接數。簡單說是指同一個賬號能夠同時連接到mysql服務的最大連接數。設置為0表示不限制。
目前默認值為:0不受限制。
這兒順便介紹下Max_used_connections:它是指從這次mysql服務啟動到現在,同一時刻並行連接數的最大值。它不是指當前的連接情況,而是一個比較值。如果在過去某一個時刻,MYSQL服務同時有1000個請求連接過來,而之后再也沒有出現這么大的並發請求時,則Max_used_connections=1000.請注意與show variables 里的max_user_connections的區別。默認為0表示無限大。
查看max_user_connections值
show variables like 'max_user_connections';
thread_concurrency
該值的正確與否, 對mysql的性能影響很大, 在多個cpu(或多核)的情況下,錯誤設置了thread_concurrency的值, 會導致mysql不能充分利用多cpu(或多核), 出現同一時刻只能一個cpu(或核)在工作的情況。
thread_concurrency應設為CPU核數的2倍. 比如有一個雙核的CPU, 那thread_concurrency 的應該為4; 2個雙核的cpu, thread_concurrency的值應為8.
比如:根據上面介紹我們目前系統的配置,可知道為4個CPU,每個CPU為8核,按照上面的計算規則,這兒應為:4*8*2=64
查看系統當前thread_concurrency默認配置命令:
show variables like 'thread_concurrency';
skip-name-resolve
禁止MySQL對外部連接進行DNS解析,使用這一選項可以消除MySQL進行DNS解析的時間。但需要注意,如果開啟該選項,則所有遠程主機連接授權都要使用IP地址方式,否則MySQL將無法正常處理連接請求!
innodb_buffer_pool_size
主要針對InnoDB表性能影響最大的一個參數。功能與Key_buffer_size一樣。InnoDB占用的內存,除innodb_buffer_pool_size用於存儲頁面緩存數據外,另外正常情況下還有大約8%的開銷,主要用在每個緩存頁幀的描述、adaptive hash等數據結構,如果不是安全關閉,啟動時還要恢復的話,還要另開大約12%的內存用於恢復,兩者相加就有差不多21%的開銷。假設:12G的innodb_buffer_pool_size,最多的時候InnoDB就可能占用到14.5G的內存。若系統只有16G,而且只運行MySQL,且MySQL只用InnoDB,
那么為MySQL開12G,是最大限度地利用內存了。
另外InnoDB和 MyISAM 存儲引擎不同, MyISAM 的 key_buffer_size 只能緩存索引鍵,而 innodb_buffer_pool_size 卻可以緩存數據塊和索引鍵。適當的增加這個參數的大小,可以有效的減少 InnoDB 類型的表的磁盤 I/O 。
當我們操作一個 InnoDB 表的時候,返回的所有數據或者去數據過程中用到的任何一個索引塊,都會在這個內存區域中走一遭。
可以通過 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 計算緩存命中率,並根據命中率來調整 innodb_buffer_pool_size 參數大小進行優化。值可以用以下命令查得:show status like 'Innodb_buffer_pool_read%';
innodb_log_buffer_size
這是InnoDB存儲引擎的事務日志所使用的緩沖區。類似於Binlog Buffer,InnoDB在寫事務日志的時候,為了提高性能,也是先將信息寫入Innofb Log Buffer中,當滿足innodb_flush_log_trx_commit參數所設置的相應條件(或者日志緩沖區寫滿)之后,才會將日志寫到文件 (或者同步到磁盤)中。可以通過innodb_log_buffer_size 參數設置其可以使用的最大內存空間。
InnoDB 將日志寫入日志磁盤文件前的緩沖大小。理想值為 1M 至 8M。大的日志緩沖允許事務運行時不需要將日志保存入磁盤而只到事務被提交(commit)。 因此,如果有大的事務處理,設置大的日志緩沖可以減少磁盤I/O。 在 my.cnf中以數字格式設置。
默認是8MB,系的如頻繁的系統可適當增大至4MB~8MB。當然如上面介紹所說,這個參數實際上還和另外的flush參數相關。一般來說不建議超過32MB
注:innodb_flush_log_trx_commit參數對InnoDB Log的寫入性能有非常關鍵的影響,默認值為1。該參數可以設置為0,1,2,解釋如下:
0:log buffer中的數據將以每秒一次的頻率寫入到log file中,且同時會進行文件系統到磁盤的同步操作,但是每個事務的commit並不會觸發任何log buffer 到log file的刷新或者文件系統到磁盤的刷新操作;
1:在每次事務提交的時候將log buffer 中的數據都會寫入到log file,同時也會觸發文件系統到磁盤的同步;
2:事務提交會觸發log buffer到log file的刷新,但並不會觸發磁盤文件系統到磁盤的同步。此外,每秒會有一次文件系統到磁盤同步操作。
實際測試發現,該值對插入數據的速度影響非常大,設置為2時插入10000條記錄只需要2秒,設置為0時只需要1秒,而設置為1時則需要229秒。因此,MySQL手冊也建議盡量將插入操作合並成一個事務,這樣可以大幅提高速度。根據MySQL手冊,在存在丟失最近部分事務的危險的前提下,可以把該值設為0。
query_cache_size
query_cache_size: 主要用來緩存MySQL中的ResultSet,也就是一條SQL語句執行的結果集,所以僅僅只能針對select語句。當我們打開了 Query Cache功能,MySQL在接受到一條select語句的請求后,如果該語句滿足Query Cache的要求(未顯式說明不允許使用Query Cache,或者已經顯式申明需要使用Query Cache),MySQL會直接根據預先設定好的HASH算法將接受到的select語句以字符串方式進行hash,然后到Query Cache中直接查找是否已經緩存。也就是說,如果已經在緩存中,該select請求就會直接將數據返回,從而省略了后面所有的步驟(如SQL語句的解析,優化器優化以及向存儲引擎請求數據等),極大的提高性能。根據MySQL用戶手冊,使用查詢緩沖最多可以達到238%的效率。
當然,Query Cache也有一個致命的缺陷,那就是當某個表的數據有任何任何變化,都會導致所有引用了該表的select語句在Query Cache中的緩存數據失效。所以,當我們的數據變化非常頻繁的情況下,使用Query Cache可能會得不償失
Query Cache的使用需要多個參數配合,其中最為關鍵的是query_cache_size和query_cache_type,前者設置用於緩存 ResultSet的內存大小,后者設置在何場景下使用Query Cache。在以往的經驗來看,如果不是用來緩存基本不變的數據的MySQL數據庫,query_cache_size一般256MB是一個比較合適的大小。當然,這可以通過計算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))來進行調整。 query_cache_type可以設置為0(OFF),1(ON)或者2(DEMOND),分別表示完全不使用query cache,除顯式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有顯示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes的值非常大,則表明經常出現緩沖. 如果Qcache_hits的值也非常大,則表明查詢緩沖使用非常頻繁,此時需要增加緩沖大小;
根據命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進行調整,一般不建議太大,256MB可能已經差不多了,大型的配置型靜態數據可適當調大.
可以通過命令:show status like 'Qcache_%';查看目前系統Query catch使用大小
| Qcache_hits | 1892463 |
| Qcache_inserts | 35627
命中率98.17%=1892463/(1892463 +35627 )*100
局部緩存
除了全局緩沖,MySql還會為每個連接發放連接緩沖。個連接到MySQL服務器的線程都需要有自己的緩沖。大概需要立刻分配256K,甚至在線程空閑時,它們使用默認的線程堆棧,網絡緩存等。事務開始之后,則需要增加更多的空間。運行較小的查詢可能僅給指定的線程增加少量的內存消耗,然而如果對數據表做復雜的操作例如掃描、排序或者需要臨時表,則需分配大約read_buffer_size,
sort_buffer_size,read_rnd_buffer_size,tmp_table_size 大小的內存空間. 不過它們只是在需要的時候才分配,並且在那些操作做完之后就釋放了。有的是立刻分配成單獨的組塊。tmp_table_size 可能高達MySQL所能分配給這個操作的最大內存空間了
。注意,這里需要考慮的不只有一點——可能會分配多個同一種類型的緩存,例如用來處理子查詢。一些特殊的查詢的內存使用量可能更大——如果在MyISAM表上做成批的插入
時需要分配 bulk_insert_buffer_size 大小的內存;執行 ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLE 命令時需要分配 myisam_sort_buffer_size 大小的內存。
read_buffer_size
read_buffer_size 是MySql讀入緩沖區大小。對表進行順序掃描的請求將分配一個讀入緩沖區,MySql會為它分配一段內存緩沖區。read_buffer_size變量控制這一
緩沖區的大小。如果對表的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變量值以及內存緩沖區大小提高其性能.
read_rnd_buffer_size
read_rnd_buffer_size 是MySql的隨機讀緩沖區大小。當按任意順序讀取行時(例如,按照排序順序),將分配一個隨機讀緩存區。進行排序查詢時,MySql會首先掃描一遍該緩沖,以避免磁盤搜索,提高查詢速度,如果需要排序大量數據,可適當調高該值。但MySql會為每個客戶連接發放該緩沖空間,所以應盡量適當設置該值,以避免內存開銷過大。
tmp_table_size
tmp_table_size是MySql的heap (堆積)表緩沖大小。所有聯合在一個DML指令內完成,並且大多數聯合甚至可以不用臨時表即可以完成。大多數臨時表是基於內
存的(HEAP)表。具有大的記錄長度的臨時表 (所有列的長度的和)或包含BLOB列的表存儲在硬盤上。如果某個內部heap(堆積)表大小超過tmp_table_size,MySQL可以根據需要自動將內存中的heap表改為基於硬盤的MyISAM表。還可以通過設置tmp_table_size選項來增加臨時表的大小。也就是說,如果調高該值,MySql同時將增加heap表的大小,可達到提高聯接查詢速度的效果。
thread_cache_size
默認的thread_cache_size=8,但是看到好多配置的樣例里的值一般是32,64,甚至是128,感覺這個參數對優化應該有幫助,於是查了下:
根據調查發現以上服務器線程緩存thread_cache_size沒有進行設置,或者設置過小,這個值表示可以重新利用保存在緩存中線程的數量,當斷開連接時如果緩存中還有空間,那么客戶端的線程將被放到緩存中,如果線程重新被請求,那么請求將從緩存中讀取,如果緩存中是空的或者是新的請求,那么這個線程將被重新創建,如果有很多新的線程,增加這個值可以改善系統性能.通過比較 Connections 和 Threads_created 狀態的變量,可以看到這個變量的作用。(–>表示要調整的值) 根據物理內存設置規則如下:
1G —> 8
2G —> 16
3G —> 32 >3G —> 64
mysql> show status like 'thread%';
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_cached | 0 | <—當前被緩存的空閑線程的數量
| Threads_connected | 1 | <—正在使用(處於連接狀態)的線程
| Threads_created | 1498 | <—服務啟動以來,創建了多少個線程
| Threads_running | 1 | <—正在忙的線程(正在查詢數據,傳輸數據等等操作)
+——————-+——-+
查看開機起來數據庫被連接了多少次?
mysql> show status like '%connection%';
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| Connections | 1504 | –>服務啟動以來,歷史連接數
| Max_used_connections | 2 |
+———————-+——-+
通過連接線程池的命中率來判斷設置值是否合適?命中率超過90%以上,設定合理。
(Connections - Threads_created) / Connections * 100 %
參考