第六章 優化服務器設置--高性能MySQL 施瓦茨--讀書筆記

MySql的默認配置不適用於使用大量資源,由於其通用性很高。node

不要指望改變配置文件會帶來巨大的性能提高。提高大小取決於工做負載,一般能夠經過選擇適當的配置參數獲得兩到三倍的性能提高。在這時候,性能提高就是增量的。爲了更大得提高,一般要檢查服務器架構,查詢及應用程序的架構。mysql

6.1配置基礎知識sql

  1 首先要知道MySQL從什麼地方獲取配置信息。(能夠用啓動腳本 --defaults-file=配置文件位置)數據庫

  2 配置文件被分紅了若干部分,每部分第一行都是 [程序名]緩存

mysql程序會讀取和程序名同名的部分,而且許多客戶端會讀取client部分,這兒也是放置通用設置的地方。安全

服務器一般會讀取mysqld部分。服務器

6.1.1 語法,做用域及動態性架構

  配置設置都是小寫的,使用下劃線或破折號分割單詞。併發

  配置設置有幾種做用域。一些設置在整個服務器內都有效(全局域);另一些針對每一個鏈接(會話域);還有一些只對對象有效。許多會話域的變量和全局變量是同樣的,能夠認爲是全局變量提供了默認值。若是修改了會話域變量的值,它只會在當前的鏈接內有效,鏈接關閉後值就消失了。高併發

  值得注意的例子:

  * query_cache_size變量是全局性的

  * sort_buffer_size變量有全局性的默認值,可是能夠在會話中設置

  * join_buffer_size有全局的默認值,而且能夠在會話中進行設置。

除了在配置文件中設置變量,也能夠在服務器運行的時候對某些值(不是所有值)進行設置。MySQL把它們叫作動態變量。

eg:

mysql> SET sort_buffer_size = <value>;

mysql> SET GLOBAL sort_buffer_size = <value>;

若是動態的設置了變量,那麼它們在MySQL關閉以後就會丟失。若是想保留這些設置,就應該同時更新配置文件。

變量使用不一樣的單位,應該要知道每一個變量的正確單位是什麼。eg:table_cache定義了能被緩存的表的數量,不是被緩存的字節數。

在配置文件或命令行參數中, 不少變量都能使用前綴,好比1MB。

當使用SET命令時,必須使用字面值1048576或者1024x1024。在配置文件中沒法使用表達式。

...其餘細節見原文

6.12設置變量的反作用

動態設置變量有出人意料的反作用,好比清空緩衝區。在線更改的設置可能會致使服務器作大量的工做。

...其餘細節見原文。

6.13 開始配置

設置變量的時候要當心。更大的值不老是好事情,若是將值設置得過高,很容易引起諸多問題:耗盡內存,致使服務器使用交換區,耗盡地址空間等。

應該老是使用監控系統來衡量改動是提高了仍是損害了服務器整體性能。

在對配置進行調優以前,應該對查詢和結構進行調優,進行一些最基本的優化,好比添加索引。調優是個漸進的過程。除非硬件,工做負載及數據是徹底靜止的,不然就要在隨後的工做中對配置再次進行調整。

這意味着並不須要一次性把服務器性能調到最好。

實際上對配置文件花費大量時間也許會收效甚微,只要讓配置保持「夠好」就好了,除非忘記了某項重要的設置,不然就不須要再次改動它。

當更改了查詢或架構的時候,就能夠回過頭再次修改配置文件。

6.2 通用調優原則

能夠把調整配置文件當作一個兩步的過程:

  在安裝的時候使用適當的初始值,而後基於工做負載進行細節調整。

 

6.2.1 內存使用調優 --配置MySQL正確地使用內存對性能相當重要。

MySQL內存消耗有兩種範疇:

能夠控制的:爲特定工做使用多少內存。

不可控的:MySQL使用多少內存來運行服務器,解析查詢及管理內部運行。

 

能夠用下面的方式進行內存調優:

1.決定MySQL能使用的內存的絕對上限

  特定系統存在內存使用上限,好比32位和64位機器......

2.決定MySQL爲每一個鏈接使用多少內存,好比排序緩衝區和臨時表

  MySQL只須要不多的內存保持鏈接開啓,必定基本內存執行查詢。須要在MySQL工做負載處於頂峯的時候爲它分配足夠的內存,不然查詢變慢,甚至失敗...

3.決定操做系統須要多少內存來很好的運行自身,包括機器上的其餘程序,好比周期性工做

...,使服務器不主動把虛擬內存保存在磁盤上。

4.假定上面的工做都已完成,就能夠把剩餘的內存非配給MySQL的緩存,好比InnoDB的緩存池

若是服務器是MySQL專用的,就不須要爲操做系統或用於處理查詢的緩存保留任何內存。

MySQL緩存比其餘東西須要更多的內存。他使用緩存來避免磁盤訪問。

對於大部分用戶來講,下面這些緩存是最重要的:

  * 操做系統爲MyISAM的數據提供的緩存

  * MyISAM鍵緩存

  * InnoDB緩存池

  * 查詢緩存--上一章節已經詳細討論了...

若是隻使用一個存儲引擎,服務器調優就容易的多。若是隻使用InnoDB,就能夠給MyISAM分配最少的資源(MySQL某些內部操做須要MyISAM)。

6.2.2 MyISAM鍵緩存

最重要的是 key_buffer_size,

建立多個命名緩衝區...

緩存命中率: 100 - ( (Key_reads * 100)  / Key_read_requests )

緩存使用百分比:100 - ( (Key_blocks_unused * key_cache_block_size) * 100 / key_buffer_size)

...

即便沒有使用MyISAM表,也要給key_buffer_size設置少許的內存,好比32MB。MySQL有時會使用MyISAM執行一些內部操做,好比給有GROUP BY的查詢提供臨時表。

MyISAM數據塊大小

......

6.2.3 InnoDB緩衝池

若是主要使用InnoDB,InnoDB緩衝池也許比其餘東西須要更多內存。

InnoDB緩衝池不只僅保存索引,它還保存了行數據及自適應的哈希索引,插入緩衝區,鎖及其它內部結構。InnoDB也使用了緩衝池幫助延遲寫入,這樣它能夠合併更多的寫入而後順序的執行。

InnoDB嚴重依賴於緩衝池,而且應該給他分配足夠的內存。

MySQL手冊建議在專用服務器上80%的物理內存分配給緩衝池。實際上若是機器內存很大的話,還能分配更多。

InnoDB沒有LOAD INDEX INTO CACHE等價的命令,須要給服務器暖身,使他爲繁重得負載作好準備,可使用查詢進項全表或全索引掃描。

少數狀況下,很大的緩衝池(好比50G)會致使長時間得延遲......

能夠改變innodb_max_dirty_pages_pct的值,讓InnoDB改變保留在緩衝池中被修改的頁面的數量。...

6.2.4線程緩存

線程緩存保存了和當前鏈接無關的線程。這些線程能夠提供新鏈接使用。

...

只要緩存中有自由的線程,MySQL就能很快的響應鏈接請求,由於它不須要爲每一個鏈接都建立新的線程。

thread_cache_size定義了MySQL能採緩存中保存的線程數量。能夠經過觀察threads_created變量的值,以肯定線程緩存是否足夠大。

每秒建立的線程數量少於10個,緩存的大小就是足夠的。

一個好辦法是觀察Threads_connected的值,而且把thread_cache_size的值設置的足夠大,以處理波動的負載。

.......

 6.2.5  表緩存

表緩存存儲了能表示表的對象。緩存中每一個對象都包含了解析表後生成的.frm文件和其餘數據,對象中的其餘東西依賴於標的存儲引擎。

表緩存有助於複用資源。

表緩存的設計有點以MyISAM爲中心,對於InnoDB來講,表緩存沒那麼重要,InnoDB在不少方面都不會依賴於它(例如保存文件描述符,InnoDB爲此有本身的表緩存)。可是,InnoDB仍是能夠從解析後的.frm文件中獲益。

表緩存被分紅兩個部分:一部分爲打開表。另外一部分爲表的定義(經過table_open_cache和talbe_definition_cache定義).....一般能夠吧table_definition_cache的值設置的足夠高,以緩存全部表的定義。

Opened_tables的值很大或者正在上升,就說明表緩存不夠大,應該增長系統變量table_cache的值(在MySQL中時table_open_cache)

若是MySQL不能打開更多文件的錯誤提示,更改open_files_limit解決這個問題。

線程和表緩存其實都不會使用太多內存,他們的好處在於能夠保存資源。在高併發條件下,提供高效率。

6.2.6 InnoDB數據字典

InnoDB本身有對每一個表的緩存,叫作"表定義緩存"或者"數據字典",它是不可配置的。

當InnoDB打開一個表的時候,它就向字典中添加一個相應的對象。表關閉時,他不會被從字典中刪除。

若是用innode_file_per_table選項,那麼對InnoDB任什麼時候候能打開的.ibd文件數量還有另外一個限制。這是由InnoDB存儲引擎處理的,不是MySQL服務器,它受innodb_open_files的控制。

InnoDB爲每一個.idbw文件使用全局文件描述符。給innodb_open_files設置足夠大,這樣服務器就能夠保留全部同時打開的.ibd文件。

6.3 MySQL I/O調優

一些配置選項能夠影響MySQL把數據同步到硬盤和進行恢復的方式。
他們一般對性能有很大影響。由於這其中涉及了昂貴得I/O操做。他們表明了性能和數據安全的折中。
一般來講,保證數據被當即而連續地寫入磁盤代價是很高的。
若是願意承擔數據不能被真正寫入的風險,能夠增長併發減小I/O等待時間,可是要決定能承受多大風險。

6.3.1 MyISAM I/O調優 -- 因不用此存儲引擎,此處忽略

6.3.2 InnoDB I/O調優
能夠控制InnoDB如何恢復,還能控制他如何打開表及刷寫數據,他們極大地影響了恢復和整體性能。
innoDB恢復過程是自動的而且在InnoDB啓動的時候總會運行,可是仍是能夠影響他的行爲。
它有複雜的鏈式緩衝區和文件,使它能夠改進性能而且保證ACID屬性,而且鏈上每個環節都是可配置的。


對於普通使用者,一個很重要的配置是InnoDB日誌文件的大小,InnoDB如何刷寫日誌緩衝區,以及InnoDB如何執行I/O.

--InnoDB事務日誌

InnoDB使用日誌來減小提交事務的開銷。它不是在每次事務提交的時候就把緩衝池刷寫磁盤上,而是記錄了事務。
事務對數據和索引作出的改變一般會被映射到表空間的隨機位置,因此將這些改變寫到磁盤上會引發隨機I/O.
做爲一條原則,隨機I/O比順序I/O開銷要高得多,由於它須要時間在磁盤上找到正確的位置,而且還要等磁頭移到相應位置上。

InnoDB使用自身的日誌把隨機I/O轉換爲順序I/O。一旦日誌被記錄到磁盤上,事務就是持久的了,儘管這時修改尚未被寫到數據文件中.若是發生了一些壞事(好比斷電),InnoDB能夠回放日誌並回復提交了的事務。

InnoDB最終要把改變寫到數據文件中,由於日誌大小是固定的。它以循環的方式寫日誌,當記錄達到日誌底部,就會又從頂部開始。它不會覆蓋改變沒有被應用到數據文件的記錄,由於這會消除提交的事務惟一持久性的記錄。

InnoDB使用後臺線程智能地把改變寫入到文件中。實際上,事務日誌把隨機數據文件I/O轉換爲順序日誌文件和數據文件I/O.把刷寫工做變成後臺進行可讓查詢更迅速。

日誌文件大小由innodb_log_file_size和innodb_log_files_in_group控制,而且他們對寫入的性能影響極大。這兩個文件默認大小都是5MB,總計爲10MB。對於高性能負載,這個大小是不夠的。...

--日誌文件大小和日誌緩衝。

在InnoDB改變數據的時候,他會把此次改動的記錄寫到日誌緩衝裏面。日誌緩衝保存在內存中。緩衝寫滿,事務提交或每一秒鐘,無論哪一種狀況發生,InnoDB都會把緩衝區寫到磁盤上的日誌文件中。若有大型事務,就能夠增長緩衝文件來減小I/O動做。用innodb_log_buffer_size控制。除非寫入大量巨型BLOB記錄,不然緩衝區1MB到8MB足夠了。(夠1秒用的就行)

能夠經過檢查SHOW INNODB STATUS命令的LOG部分檢測InnoDB的日誌和日誌緩衝性能,還能夠觀察Innodb_os_log_written瞭解InnoDB向日志寫入了多少數據。

--InnoDB如何刷寫日誌緩衝。
日誌緩衝區必須被刷寫到持久性存儲中,以保證提交了的事務能徹底持久化。若是比起持久性,更在乎性能,能夠改變innodb_log_at_trx_commit的值來控制日誌緩存被刷寫到什麼地方及刷寫頻率

--InnoDB 如何打開並清寫日誌和數據文件
innodb_flush_method選項讓你能夠配置InnoDB實際與文件系統進行交互的方式。--給默認值就行--先無論

--InnoDB表空間

 

InnoDB把數據保存在表空間中。
表空間其實是快月了磁盤上的一個或多個文件的虛擬文件系統。
InnoDB出於不少考慮使用表空間,不只爲了存儲表和索引。它保留了本身的撤銷日誌,插入緩存,雙寫緩存,以及表空間的其餘內部結構。

 

配置表空間。可使用innodb_data_file_path定義表空間文件。這些文件都在innodb_data_home_dir定義的目錄中。
eg:
innodb_data_home_dir = /var/lib/mysql/data
innodb_data_file_path = ibdata1:1G;ibdata2:1G:autoextend

 

autoextend:表空間耗盡後自動增加。
max:限制延伸文件最大爲xx

 

innodb_file_per_table:使InnoDB爲每一個表使用一個文件,它在數據庫目錄中以「表名.ibd」保存數據。

 

舊數據版本和表空間。InnoDB的表空間在寫入負荷很重的環境中會增加得很大。
有的問題不是出在沒提交的事務上,而是出在工做負載上,清理進程是單線程的,它跟不上須要被清理的老數據的數量。
SHOW INNODB STATUS的輸出有助於鎖定問題。...
若是有不少未被清理的事物而且表空間因它而增加,就能夠強制mysql變慢,以使清理線程能跟上數據的變化。
爲了減緩寫入,能夠把innodb_max_purge_lag設置爲0之外的值。這個值表示等待清理的事物的最大數量,一單超過這個值,InnoDB就會延遲更新數據的事物,要知道負載才能決定這個值的最佳大小。

--雙寫緩衝
InnoDB在對頁面進行部分寫入的時候使用了雙緩衝,防止數據損壞。
部分寫入發生在磁盤寫入沒有所有完成,而且只有16KB頁面的一部分被寫入的時候。
有不少緣由(崩潰,缺陷等)會致使數據被部分寫入,雙寫緩存在這種狀況下保護了數據。

--另外的I/O調優 Sync_binlog

 

6.4 MySQL併發調優

 

6.4.1 MyISAM併發調優 --越過

 

6.4.2 InnoDB併發調優

 

InnoDB是爲高併發設計的,可是並不完美。InnoDB的結構仍然基於有限內存,單CPU和磁盤系統。
InnoDB某些方面的性能在高併發條件下降低的很快,惟一的解決辦法是限制併發。
經過SHOW INNODB STATUS 輸出中的 SEMAPHORES部門來確認是否發生了併發問題。
InnoDB用本身的「線程調度」程序來控制線程如何進入InnoDB的內核訪問數據,以及進入內核以後能夠執行的動做。

 

innodb_thread_concurrency變量 限制了一次多少線程進入內核。
併發 = CPU數量x硬盤的數量x2

 

innodb_thread_sleep_delay

相關文章
相關標籤/搜索