mysql優化【轉】
最近聽講了博森瑞老師的mysql優化公開課,這個是我整理的筆記。
現在說一下mysql的內存和I/O方面的兩個特點。
一、 mysql內存特點:
1、 也有全局內存和每個session的內存(每個session類似於oracle的sga和pga),但是針對每個session的內存,我們不要給它分配過大。如果對每個session的內存分配過大,會造成oom的發生。在高並發下,增加物理內存就可以減少物理I/O。所以mysql的內存管理比oracle簡單一些。
2、在oracle裏面有library cache,用來緩存執行計劃的。但是mysql不會緩存執行計劃,mysql有類似於oracle的Qcache,Qcache是用來緩存sql語句的,但是在生產中建議關掉此功能,因為該功能很雞肋,它的功能體現不了那麽大的作用。
3、mysql的查詢分析器很高效,mysql不緩存執行計劃,但是並不會出現像oracle那種硬解析的問題。
4、對於內存方面的分配,如果是單實例的Mysql,建議分配50%到70%的物理內存給mysql。
二、mysql I/O方面的特點
mysql有binlog、undo log和redo log三個日誌文件都是順序寫I/O的方式。mysql的數據文件是包含著隨機寫I/O和順序寫I/O的。
目前mysql有innodb和myisam存儲引擎。有人可能會說myisam的存儲引擎要比innodb的存儲引擎快。其實並不是這樣的。為什麽這麽說呢哈?innodb主要根據主鍵檢索數據時很快,因為主鍵裏包含行的數據信息,而且,對於innodb,它是雙鏈表結構, 所以他很快就能找到數據。另外,Innodb既緩存數據文件,也緩存索引文件。但是針對myisam來說呢,myisam只緩存索引文件。所以,一個很簡單的道理,你說是從內存讀快,還是從磁盤讀快。答案肯定是從內存讀取快。所以結論就是,Innodb要比Myisam存儲引擎快。
優化思路:
1、發現問題的過程
當數據庫慢了,要搞清是什麽問題導致系統慢了,是系統的問題,還是開發的問題,還是數據庫的問題;
2、找到問題後,鎖定問題瓶頸點;
鎖定瓶頸點的過程,分為兩個層面。一個是系統層面,一個是數據庫層面。
2.1 系統層面
系統層面就需要我們學習一些linux方面的知識,利用linux的知識,來鎖定問題的瓶頸在哪。top命令可以看哪個進程占用cpu最高,查看負載,可以查看內存。
vmstat可以查看內存、cpu、i/o。
sar –u查看cpu
sar -d 查看io
- sar -r查看內存的。
2.2數據庫層面
現在Mysql默認存儲引起是innodb。
1、 show engine innodb status
通過show innodb status看鎖的情況,看數據有沒有鎖,有沒有死鎖,有沒有事務狀態,看看一些頁的情況,看看現在有沒有老頁和新頁的移動。
2、 slow log
看慢日誌,制定時間,有好多工具可以分析慢日誌(如percona公司的),找到top10最慢的sql(一般優先處理頻率最高的前十條SQL語句)
也可以通過圖形化的工具,找到最慢的sql,然後找開發溝通,商討是在業務上更改呢,還是針對這條SQL來進行優化。我們的目的就是讓sql越簡單越好。
3、 show global status
show global status查看數據庫整體的性能,看哪個點需要調整一下,看碎片是如何產生,碎片產生多少,如何清理碎片。看每秒鐘產生的TPS有多少。
4、 show processlist
show processlist查看整個mysql鏈接的一個情況,註意看wait timeout 和inactive timeout ,主要減少不活躍的連接,這樣可以把那些消耗的內存收回,從而防止omq的發生。
5、Pt-ioprofile
pt-ioprofile是第三方工具,查看innodb內部有哪些表是最活躍的,因為大部分的優化,都是在SQL瓶頸點。當我們鎖定到這些表,我們就可以針對這些表做一些文章了,看這些表是否需要添加索引,是否進行碎片的整理。所以這個工具也很重要。
3、 優化方法的初定
我們鎖定到了問題的瓶頸點了,就需要制定優化方案。
4、 制定優化方案。
5、優化方案的測試
我們不能因為優化一個問題點,影響其他的業務。所以鎖定問題是從面到點,但是優化測試是從點到面。我們只要把這個點解決問題了,而不要影響全面。所以測試時一定要找測試環境,方案能真正在生產線上實施再實施。
6、方案的實施
7、問題解決了
一定要做好記錄,想清楚為什麽發生這樣的問題,避免下次再發生。這也是考驗一個人的好的學習方式。
在硬件角度的優化。
從系統bios層面
從系統bios層面,有個參數叫dapc,它表示每瓦的電能都能產生最大的功效,可以讓cpu發揮它最大的功效。
在bios層面,還有個參數是內存頻率,一定要調成max performance。
在bios層面還有一個cae處理器,當它處於閑置狀態的時候,我們可以禁用處理器,使其處於最低的狀態。
關於TPS高,業務高
關於TPS高,業務高的一個情況,這種情況一定要配置陣列卡,一定要配置cache模塊和bbu模塊。bbu模塊是用來提供我後備的電量,當機器斷電了,我的bbu模塊可以去充當電源,保證數據不會丟失,使數據寫到cache裏面。現在新的服務器都是電容模式的bbu了,性能會更好。
關於陣列卡策略的問題
關於陣列卡策略的問題,一定要選擇wb(write bike),就是當寫數據的時候,一定要先寫到cache卡裏面,然後通過陣列卡把數據刷到磁盤,這樣能提高我們的IOPS。一定要禁用wthrow,因為這種直接寫磁盤是非常耗性能的。
關於關閉預讀功能
關於關閉預讀功能,就是讓緩存踏踏實實做寫緩存的作用。不要開啟預讀,不要開啟數據頁,到我的cache裏面,這麽做沒有任何作用。
關於陣列級別的選擇
關於陣列級別的選擇,對於mysql數據庫,建議用raid 1+0。
有人說,用raid5也不錯,但是raid5的寫乘法數據是4。為什麽是4呢,因為raid5有讀數據,讀校驗位、寫數據,寫校驗位。但是raid10,它只有雙寫,也就是raid10的系數是2。所以raid10寫的i/o一定要比raid5高,不過raid5讀i/o比raid10可能好一些,但是針對oltp這種系統,推薦用raid10。
關於磁盤上的策略
關於關閉磁盤上的策略,一定要關閉磁盤上的cache策略。因為我們沒有必要開它,這樣可以防止丟失數據。
關於選盤的問題
建議上SSD或PCIE-SSD的磁盤,這樣可以提高iops上百倍或者上千倍。
關於swappiness值大小的調整
swappiness值大小對於我們如何使用swap分區是有很多聯系的。當swappiness設置為0,就是充分利用虛擬內存。當swappines設置為100,表示能用swap分區,就用swap分區。
在redhat 6版本之前,swappiness可以設置成0,;但是大於redhat6最好設置成10;到了redhat 7以上,一定要謹慎設置swappiness設置成0,因為如果設置成0了,在redhat 7可能會發生omq。
關於I/O調度器的選擇
IO調度器,首選deadline,其次用noop,不要用默認的cfq,默認是非常的不好的。
關於文件系統的選擇
首先xfs,其次ext4。
i
############
innodb是Mysql的默認存儲引擎。影響innodb引擎最重要的參數是innodb_buffer_pool_size,它就相當於oracle的buffer cache,是用來緩存數據用的。
在單實例的mysql,最好設置innodb_buffer_pool_size設置為50%~70%的物理內存大小。
innodb_data_file_path,該參數就是分配共享表空間的大小。它默認是10m。但是我們建議將其設置成1G,這樣可以避免後期數據暴漲很消耗性能。
innodb_log_file_size,該參數不要設置的過大,因為該參數相當於oracle裏面的redo。如果把該參數設置的過大,當數據庫crash的時候,恢復數據就會很慢。
transaction_isolation,表示事務隔離級別。對於mysql需要什麽樣的事務隔離級別,是需要一步一步去選擇的。對於oracle來講,事務隔離級別就是默認的提交讀。但是對於mysql,有默認的提交讀,也有可重復讀,還有臟讀和串讀。建議使用Mysql的可重復讀(r模式),因為這種模式可以保證數據的一致性,可以避免發生一個事務提交了,在另一個事務中能看到他提交的東西。如果事務提交了,在另外一個事務中能看到他提交的東西,這樣就違背了事務一致性的情況的。
sort_buffer_size、read_buffer_size、join_buffer_size三個參數,可以理解為oracle的pga。這三個參數不用設置過大,大概幾兆,幾十兆就行。另外oracle的pga也不要設置的過大。
general_log,log_bin,sync_binlog,long_query_time,interactive_timeout,wait_timeout,max_connections
在生產上,不要開全日誌(general_log),因為開了全日誌,它就會記錄全部的sql語句,這樣很影響mysql性能。
對於binlog日誌,一定要開此功能,因為這樣可以實現復制的功能,也可以實現binlog恢復的功能。
對於sync_binlog,該參數數值的大小,關系到數據庫寫binlog情況的問題。sync_binlog=0,表示我每一秒刷一次binlog,sync_binlog=1表示每秒我都刷,保證他不會丟;當sync_binlog=2,表示交給操作系統,數據庫不管了。
對於long_query_time,表示慢查詢時間的一個情況,可以設置0.xxxx秒的慢查詢。對出現頻率高的慢sql進行優化。
可以通過show processlist看一些交互式和非交互式的時間等待。對於interactive_timeout和wait_timeout這兩個參數我們不要設置的過大,一般這兩個值設置的一樣,在沒有連接池的情況,設置成5分鐘就行了。
max_connections,當用戶連接數超過這個max_connections時,會報錯。但註意,報錯時,不要盲目的增大max_connections這個參數。因為如果max_connections設置的過大,會發生數據庫被連暴了,塌了的情況,是很危險。那麽我們應該如何調整呢?其實出現這種情況會聯系到好多的參數的,比如可以減少並發參數的值來減少連接數,或者觀察數據庫sql語句,分析到底是業務的問題還是數據庫的問題。不要什麽事情都往自己身上攬,拿出證據,證明這個問題就不是我DBA的問題。
選擇存儲引擎,是針對業務來講。針對oltp 默認就是Innodb。到了mysql 5.7有可能myisam會消失。
innodb存儲引擎支持事務,支持行鎖,鎖的粒度更低,所以並發性很好,當發生故障可以根據redo和Undo進行恢復。Innodb是緩存數據和索引的,但是Myisam只緩存索引,而且myisam的數據和索引是分開的。
一定要設置自增主鍵。如果你不設置自增主鍵,也沒有關系,這時候Mysql會給它一個6字節的主鍵,但是這樣會很消耗性能的。所以設置自增主鍵是一個必須的選項。
關於時間日期,ipv4類型和數據類型可以用int
避免使用text/blob這種大數據類型。如果非要用大數據類型,可以單獨把大數據類型放在一張表上存儲。
定義字段的時候盡量要定義Not null,因為索引是不含Null字段的。
選擇性低的字段不要創建索引,像男女這樣的字段不要創建索引,創建索引沒有意義。因為mysql優化器是很智能的,重復值出現很多,mysql可能就不走索引,而是走全表掃描了。
對於排序和分組字段上,一定要創建索引。
索引不要太多,因為update,會使索引的頁進行翻轉,對性能有很大的下降。
聯合索引優於單列索引,聯合索引可以縮短整個段池搜索的一個範圍,它比單列索引要好。
像一些字符類型,如果可能只用到前面幾個字符,而不需要整個字段建索引,這叫前綴索引,我們可以建立一個前綴索引,我只搜那幾個字段。
索引掃描記錄的述超過30%,就會走全表掃描
模糊匹配查詢的雙%%不會用到索引的。但是去掉左邊的%,%號在最後一位可能會用到索引。
聯合索引,第一個查詢條件如果不是最做索引列,也不會用到索引,這就是最左前綴原則。
聯合索引,如果第一個索引列使用範圍查詢(> 、=、<、>=、<=),那用到索引也是部分索引,有可能只用到第一個索引了,後面的索引數據庫都用不到。
兩個獨立的索引,一個用來檢索,一個用來排序,可能只用到一個。mysql 5.6有ITC這項功能。
最忌諱在索引的字段上使用函數,這樣是不會走索引的。
Q&A
sga是內存全局區,pga是用戶的一個session連接上數據庫單獨分配給的內存。
mysql用的最多的集群是MHA。oracle的集群是RAC。
為什麽會產生死鎖?就是因為共搶一塊東西,你要我的東西,我又要你的東西,從而造成死循環,用show innodb status定位死鎖產生在哪。
最好關閉磁盤的cache策略,因為寫在cache裏面,容易發生數據丟失,所以建議關閉磁盤的cache策略。
有問題留言,
保證業務的穩定,保證數據庫快速。
主從分離和DBA沒有關系,只需要開發在代碼裏面寫好了。
現在mysql架構,就是用MHA。
不是說數據量大了,就進行優化,而是出現性能問題了再進行優化。看索引建沒建。
轉自
mysql優化--博森瑞-czxin788-ITPUB博客
http://blog.itpub.net/28916011/viewspace-1758440/
mysql優化【轉】