互聯(lián)網(wǎng)金融MySQL優(yōu)化參數(shù)標(biāo)準(zhǔn)
下面針對一些參數(shù)進(jìn)行說明屡谐。當(dāng)然還有其它的設(shè)置可以起作用叮贩,取決于你的負(fù)載或硬件:在慢內(nèi)存和快磁盤疾棵、高并發(fā)和寫密集型負(fù)載情況下黎侈,你將需要特殊的調(diào)整。然而這里的目標(biāo)是讓你可以快速地獲得一個穩(wěn)健的MySQL配置涝桅,而不用花費太多時間在調(diào)整一些無關(guān)緊要的MySQL設(shè)置或讀文檔拜姿,找出哪些設(shè)置對你來說是重要的。
InnoDB配置
從MySQL 5.5版本開始冯遂,InnoDB就是默認(rèn)的存儲引擎并且它比任何其它存儲引擎的使用要多得多蕊肥。那也是為什么它需要小心配置的原因。
1 innodb_file_per_table
表的數(shù)據(jù)和索引存放在共享表空間里或者單獨表空間里债蜜。我們的工作場景安裝是默認(rèn)設(shè)置了innodb_file_per_table = ON晴埂,這樣也有助于工作中進(jìn)行單獨表空間的遷移工作究反。MySQL 5.6中寻定,這個屬性默認(rèn)值是ON。
2 innodb_flush_log_at_trx_commit
默認(rèn)值為1精耐,表示InnoDB完全支持ACID特性狼速。當(dāng)你的主要關(guān)注點是數(shù)據(jù)安全的時候這個值是最合適的,比如在一個主節(jié)點上卦停。但是對于磁盤(讀寫)速度較慢的系統(tǒng)向胡,它會帶來很巨大的開銷,因為每次將改變flush到redo日志都需要額外的fsyncs惊完。
如果將它的值設(shè)置為2會導(dǎo)致不太可靠(unreliable)僵芹。因為提交的事務(wù)僅僅每秒才flush一次到redo日志,但對于一些場景是可以接受的小槐,比如對于主節(jié)點的備份節(jié)點這個值是可以接受的拇派。如果值為0速度就更快了,但在系統(tǒng)崩潰時可能丟失一些數(shù)據(jù):只適用于備份節(jié)點凿跳。說到這個參數(shù)就一定會想到另一個sync_binlog件豌。
3 innodb_flush_method
這項配置決定了數(shù)據(jù)和日志寫入硬盤的方式。一共有三種方式控嗜,我們默認(rèn)使用O_DIRECT 茧彤。O_DIRECT模式:數(shù)據(jù)文件的寫入操作是直接從mysql innodb buffer到磁盤的,并不用通過操作系統(tǒng)的緩沖疆栏,而真正的完成也是在flush這步曾掂,日志還是要經(jīng)過OS緩沖庶香。
4 innodb_log_buffer_size
這項配置決定了為尚未執(zhí)行的事務(wù)分配的緩存。其默認(rèn)值(1MB)一般來說已經(jīng)夠用了忧设,但是如果你的事務(wù)中包含有二進(jìn)制大對象或者大文本字段的話崔泵,這點緩存很快就會被填滿并觸發(fā)額外的I/O操作∠瘴郏看看Innodb_log_waits狀態(tài)變量痹愚,如果它不是0,增加innodb_log_buffer_size蛔糯。
5 innodb_buffer_pool_size
這個參數(shù)應(yīng)該是運維中必須關(guān)注的了拯腮。緩沖池是數(shù)據(jù)和索引緩存的地方,它屬于MySQL的核心參數(shù)蚁飒,默認(rèn)為128MB动壤,正常的情況下這個參數(shù)設(shè)置為物理內(nèi)存的60%~70%。(不過我們的實例基本上都是多實例混部的淮逻,所以這個值還要根據(jù)業(yè)務(wù)規(guī)模來具體分析琼懊。)
6 innodb_log_file_size
這是redo日志的大小。redo日志被用于確保寫操作快速而可靠并且在崩潰時恢復(fù)爬早。如果你知道你的應(yīng)用程序需要頻繁地寫入數(shù)據(jù)并且你使用的是MySQL 5.6哼丈,那么你可以一開始就把它這是成4G。(具體大小還要根據(jù)自身業(yè)務(wù)進(jìn)行適當(dāng)調(diào)整)
7 innodb_support_xa
innodb_support_xa可以開關(guān)InnoDB的XA兩段式事務(wù)提交筛严。默認(rèn)情況下醉旦,innodb_support_xa=true,支持XA兩段式事務(wù)提交桨啃。由于XA兩段式事務(wù)提交導(dǎo)致多余flush等操作车胡,性能影響會達(dá)到10%,所有為了提高性能照瘾,有些DBA會設(shè)置innodb_support_xa=false匈棘。這樣的話,redolog和binlog將無法同步析命,可能存在事務(wù)在主庫提交主卫,但是沒有記錄到binlog的情況。這樣也有可能造成事務(wù)數(shù)據(jù)的丟失碳却。
8 innodb_additional_mem_pool_size
該參數(shù)用來存儲數(shù)據(jù)字段信息和其他內(nèi)部數(shù)據(jù)結(jié)構(gòu)队秩。表越多,需要在這里分配的內(nèi)存越多昼浦。如果InnoDB用光了這個池內(nèi)的內(nèi)存馍资,InnoDB開始從操作系統(tǒng)分配內(nèi)存,并且往MySQL錯誤日志寫警告信息,默認(rèn)8MB鸟蟹。一般設(shè)置16MB乌妙。
9 max_connections
MySQL服務(wù)器默認(rèn)連接數(shù)比較小,一般也就100來個最好把最大值設(shè)大一些建钥。一般設(shè)置500~1000即可每一個鏈接都會占用一定的內(nèi)存藤韵,所以這個參數(shù)也不是越大越好。有的人遇到too many connections會去增加這個參數(shù)的大小熊经,但其實如果是業(yè)務(wù)量或者程序邏輯有問題或者sql寫的不好泽艘,即使增大這個參數(shù)也無濟于事,再次報錯只是時間問題镐依。在應(yīng)用程序里使用連接池或者在MySQL里使用進(jìn)程池有助于解決這一問題匹涮。
Seesion級的內(nèi)存分配
max_threads(當(dāng)前活躍連接數(shù))* (
read_buffer_size-- 順序讀緩沖,提高順序讀效率
+read_rnd_buffer_size-- 隨機讀緩沖槐壳,提高隨機讀效率
+sort_buffer_size-- 排序緩沖然低,提高排序效率
+join_buffer_size-- 表連接緩沖,提高表連接效率
+binlog_cache_size-- 二進(jìn)制日志緩沖务唐,提高二進(jìn)制日志寫入效率?
+tmp_table_size-- 內(nèi)存臨時表雳攘,提高臨時表存儲效率
+thread_stack-- 線程堆棧,暫時寄存SQL語句/存儲過程
+thread_cache_size-- 線程緩存枫笛,降低多次反復(fù)打開線程開銷
+net_buffer_length-- 線程持連接緩沖以及讀取結(jié)果緩沖
+bulk_insert_buffer_size-- MyISAM表批量寫入數(shù)據(jù)緩沖
)
global級的內(nèi)存分配
global buffer(全局內(nèi)存分配總和) =
innodb_buffer_pool_size
-- InnoDB高速緩沖吨灭,行數(shù)據(jù)、索引緩沖崇堰,以及事務(wù)鎖沃于、自適應(yīng)哈希等
+ innodb_additional_mem_pool_size
-- InnoDB數(shù)據(jù)字典額外內(nèi)存涩咖,緩存所有表數(shù)據(jù)字典
+innodb_log_buffer_size
-- InnoDB REDO日志緩沖海诲,提高REDO日志寫入效率
+key_buffer_size
-- MyISAM表索引高速緩沖,提高M(jìn)yISAM表索引讀寫效率
+query_cache_size
--查詢高速緩存檩互,緩存查詢結(jié)果特幔,提高反復(fù)查詢返回效率+table_cahce -- 表空間文件描述符緩存,提高數(shù)據(jù)表打開效率
+table_definition_cache
--表定義文件描述符緩存闸昨,提高數(shù)據(jù)表打開效率
參數(shù)的優(yōu)化最終目的是讓MySQL更好地利用資源通過合理地控制內(nèi)存的分配蚯斯,合理的CPU使用建議降低Session的內(nèi)存分配。
10 server-id
復(fù)制架構(gòu)時確保 server-id 要不同饵较,通常主ID要小于從ID拍嵌。
11 log_bin
如果你想讓數(shù)據(jù)庫服務(wù)器充當(dāng)主節(jié)點的備份節(jié)點,那么開啟二進(jìn)制日志是必須的循诉。如果這么做了之后横辆,還別忘了設(shè)置server_id為一個唯一的值。就算只有一個服務(wù)器茄猫,如果你想做基于時間點的數(shù)據(jù)恢復(fù)狈蚤,這(開啟二進(jìn)制日志)也是很有用的:從你最近的備份中恢復(fù)(全量備份)困肩,并應(yīng)用二進(jìn)制日志中的修改(增量備份)。
二進(jìn)制日志一旦創(chuàng)建就將永久保存脆侮。所以如果你不想讓磁盤空間耗盡锌畸,你可以用 PURGE BINARY LOGS 來清除舊文件,或者設(shè)置expire_logs_days 來指定過多少天日志將被自動清除靖避。記錄二進(jìn)制日志不是沒有開銷的潭枣,所以如果你在一個非主節(jié)點的復(fù)制節(jié)點上不需要它的話,那么建議關(guān)閉這個選項幻捏。
12 skip_name_resolve
當(dāng)客戶端連接數(shù)據(jù)庫服務(wù)器時卸耘,服務(wù)器會進(jìn)行主機名解析,并且當(dāng)DNS很慢時粘咖,建立連接也會很慢蚣抗。因此建議在啟動服務(wù)器時關(guān)閉skip_name_resolve選項而不進(jìn)行DNS查找。唯一的局限是之后GRANT語句中只能使用IP地址了瓮下,因此在添加這項設(shè)置到一個已有系統(tǒng)中必須格外小心翰铡。
13 sync_binlog
sync_binlog 的默認(rèn)值是0,像操作系統(tǒng)刷其他文件的機制一樣讽坏,MySQL不會同步到磁盤中去而是依賴操作系統(tǒng)來刷新binary log锭魔。
當(dāng)sync_binlog =N (N>0) ,MySQL 在每寫N次二進(jìn)制日志binary log時路呜,會使用fdatasync()函數(shù)將它的寫二進(jìn)制日志binary log同步到磁盤中去迷捧。當(dāng)innodb_flush_log_at_trx_commit和sync_binlog 都為 1 時是最安全的,在mysqld服務(wù)崩潰或者服務(wù)器主機crash的情況下胀葱,binary log只有可能丟失最多一個語句或者一個事務(wù)漠秋。但是魚與熊掌不可兼得,雙1會導(dǎo)致頻繁的IO操作抵屿,因此該模式也是最慢的一種方式庆锦。出于我們的業(yè)務(wù)考慮在業(yè)務(wù)壓力允許的情況下默認(rèn)的都是雙1配置。
14 log_slave_update
當(dāng)業(yè)務(wù)中需要使用級聯(lián)架構(gòu)的時候log_slave_update = 1這個參數(shù)必須打開轧葛,否者第三級可能無法接收到第一級產(chǎn)生的binlog搂抒,從而無法進(jìn)行數(shù)據(jù)同步。
15 tmpdir
如果內(nèi)存臨時表超出了限制尿扯,MySQL就會自動地把它轉(zhuǎn)化為基于磁盤的MyISAM表求晶,存儲在指定的tmpdir目錄下.因此盡可能將tmpdir配置到性能好速度快的存儲設(shè)備上。
16 慢日志相關(guān)
slow_query_log = 1 #打開慢日志
slow_query_log_file = /mysql/log/mysql.slow
long_query_time = 0.5 #設(shè)置超過多少秒的查詢會入慢日志
其他問題
1 SSD對參數(shù)的影響
隨著科學(xué)技術(shù)的發(fā)展衷笋,越來越多的存儲設(shè)備開始由傳統(tǒng)的機械組件轉(zhuǎn)向由電子元件組成的永久存儲芳杏,且價錢越來越能讓企業(yè)接受。存儲組件速度提升后,再用傳統(tǒng)機械組件的DB配置就顯得浪費了蚜锨,所以就需要針對不同的存儲技術(shù)對MySQL配置作出調(diào)整档插,比如 innodb_io_capacity需要調(diào)大, 日志文件和redo放到機械硬盤亚再, undo放到SSD郭膛, atomic write不需要Double Write Buffer, InnoDB壓縮氛悬, 單機多實例+cgroup等等则剃。分析 I/O 情況,動態(tài)調(diào)整 innodb_io_capacity 和 innodb_max_dirty_pages_pct如捅;試圖調(diào)整 innodb_adaptive_flushing棍现,查看效果。
2 線程池設(shè)置
針對innodb_write_io_threads 和 innodb_read_io_threads 的調(diào)優(yōu)我們目前沒有做镜遣,但我相信調(diào)整為8或者16己肮,系統(tǒng) I/O 性能會更好。還有悲关,需要注意以下幾點:任何一個調(diào)整谎僻,都要建立在數(shù)據(jù)的支撐和嚴(yán)謹(jǐn)?shù)姆治龌A(chǔ)上,否則都是空談寓辱; 這類調(diào)優(yōu)是非常有意義的艘绍,是真正能帶來價值的,所以需要多下功夫秫筏,并且盡可能地搞明白為什么要這么調(diào)整诱鞠。
3 CPU相關(guān)
Innodb_thread_concurrency=0
Innodb_sync_spin_loops=288
table_definition_cache=2000
4 IO相關(guān)的
Innodb_flush_method 建議用O_DIRECT
Innodb_io_capacity 設(shè)置成磁盤支持最大IOPS
Innodb_wirte_io_threads=8
Innodb_read_io_threads=8
Innodb_purge_threads=1
Innodb的預(yù)讀方面,如果基于主建或是唯一索引的系統(tǒng)这敬,建議禁用預(yù)讀
Innodb_random_read_ahead = off