萬字長文淺析設定對MySQL伺服器的影響

2023-07-26 12:03:21

有很多的伺服器選項會影響這MySQL伺服器的效能,比如記憶體中臨時表的大小、排序緩衝區等。有些針對特定儲存引擎(如InnoDB)的選項,也會對查詢優化很有用。

調整伺服器的設定從某種程度來說是一個影響全域性的行為,因為每個修改都可能對該伺服器上的每個查詢造成影響。不過有些選項是針對特定型別的優化的,如果你的請求沒有滿足條件,它將沒有任何作用。

首先我們需要檢查的選項是緩衝區大小(buffer size)

每個緩衝區都有其存在的特定原因,一般的規律是大緩衝區意味著高效能,不過僅當請求可以針對該緩衝區扮演的特定角色使用大容量快取的時候。

當然,增加緩衝區大小是有代價的,下面是一些大緩衝區可能帶來的影響。

•交換區

大容量緩衝區可能會導致會使用到作業系統級別的交換區從而造成效能緩慢,這取決於系統記憶體大小。通常情況下,MySQL伺服器在它所需的所有記憶體都來自實體記憶體的時候執行最快。當它使用到交換區的時候,效能顯著下降。

當為緩衝區分配的記憶體大小超過伺服器的實體記憶體大小的時候就會使用到交換區。有一些緩衝區是針對每個使用者執行緒的。要確定這些緩衝區究竟需要多少記憶體,可以用公式 max_connections * buffer_size 來計算。計算出所有緩衝區的記憶體和,並確保小於mysqld伺服器可以使用的記憶體大小。

•啟動時間

mysqld需要分配的記憶體越多,其啟動時間就越長。

•過期資料

我們還會有伸縮性問題,大部分時候是來自執行緒間的快取共用。在這些場景中,擴充緩衝區做快取會產生記憶體碎片。你通常會在伺服器執行數小時後發現記憶體碎片問題,該問題發生在舊的資料需要從緩衝區中移除以給新資料騰出空間的時候。這會導致高速運轉的伺服器變慢。

其次我們不僅關注效能優化選項(如優化器選項),我們還會關注一些控制高可用的選項。事務執行得越安全,就需要更多的檢查和更慢地執行效能。針對這些選項,只有在你可以為了效能犧牲安全的時候才可以調優它們。

在此,當你調優分配的時候,把效能作為整體來考慮尤為重要,因為每個選項都會影響整個伺服器。

MySQL伺服器提供了大量的選項,我們可以通過多種方式來對這些選項進行設定。

1.在my.cnf組態檔中進行設定

2.在使用命令列啟動伺服器的時候設定

3.在伺服器正在執行的時候使用變數來設定

其中這些變數有些是GLOBAL型別的,有些是SESSION級別的,本文將闡述一些可以建立或能夠產生變化的選項,能夠幫助你解決MySQL發生的一些問題。

我們可以根據變數的用途來把它們分成多個不同的組:用來設定伺服器的設定目錄。限制對硬體資源的使用,改變mysqld應該如何應對一個或多個場景等。依照它們分配時間的不同,它們也可以分為不同的組,例如:當伺服器啟動的時候,一個執行緒連線建立的時候, 或者當伺服器啟動一個特定操作的時候。

一、設定選項介紹

伺服器選項

當我們使用mysql使用者端可執行檔案連線mysql伺服器時,需要指定IP地址、使用者名稱及密碼等資訊,這些資訊就是mysql使用者端程式啟動時的選項,通過這些選項可以連線到具體的mysql伺服器端上。

對於mysql伺服器端,在啟動時可以指定同時連入的使用者端數量、使用者端/伺服器端的通訊方式、表的預設儲存引擎、查詢快取的大小等資訊,

例如:向伺服器指定目錄或檔案,提醒伺服器是否開啟一個特定的紀錄檔等諸如此類的功能。

有倆個典型的故障排除情景是由這種選項導致的:

當某選項使用錯誤路徑的時候,你通常能夠在伺服器啟動的時候注意到此類問題。例如,如果你對 datadir 選項指定一條錯誤路徑,那麼 mysqld 會拒絕啟動並輸出有關的錯誤訊息

[root@dba-test ~]# /export/servers/mysql/bin/mysqld --defaults-file=/export/restore/tool/general_mysql_backup_extract_tool/mysql-5.cnf --user=mysql --datadir=/export/restore/
2023-03-22T05:50:50.004095Z 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
2023-03-22T05:50:50.004203Z 0 [Note] --secure-file-priv is set to NULL. Operations related to importing and exporting data are disabled
2023-03-22T05:50:50.004237Z 0 [Note] /export/servers/mysql/bin/mysqld (mysqld 5.7.24) starting as process 4232 ...
2023-03-22T05:50:50.012400Z 0 [Note] InnoDB: PUNCH HOLE support available
2023-03-22T05:50:50.012440Z 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2023-03-22T05:50:50.012450Z 0 [Note] InnoDB: Uses event mutexes
2023-03-22T05:50:50.012458Z 0 [Note] InnoDB: GCC builtin __sync_synchronize() is used for memory barrier
2023-03-22T05:50:50.012468Z 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2023-03-22T05:50:50.012475Z 0 [Note] InnoDB: Using Linux native AIO
2023-03-22T05:50:50.013078Z 0 [Note] InnoDB: Number of pools: 1
2023-03-22T05:50:50.013294Z 0 [Note] InnoDB: Using CPU crc32 instructions
2023-03-22T05:50:50.017366Z 0 [Note] InnoDB: Initializing buffer pool, total size = 128M, instances = 1, chunk size = 128M
2023-03-22T05:50:50.027751Z 0 [Note] InnoDB: Completed initialization of buffer pool
2023-03-22T05:50:50.030019Z 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2023-03-22T05:50:50.040071Z 0 [Note] InnoDB: The first innodb_system data file 'ibdata1' did not exist. A new tablespace will be created!
2023-03-22T05:50:50.040081Z 0 [Note] InnoDB: Need to create a new innodb_system data file 'ibdata2'.
2023-03-22T05:50:50.040290Z 0 [ERROR] InnoDB: Operating system error number 13 in a file operation.
2023-03-22T05:50:50.040295Z 0 [ERROR] InnoDB: The error means mysqld does not have the access rights to the directory.
2023-03-22T05:50:50.040298Z 0 [ERROR] InnoDB: Operating system error number 13 in a file operation.
2023-03-22T05:50:50.040301Z 0 [ERROR] InnoDB: The error means mysqld does not have the access rights to the directory.
2023-03-22T05:50:50.040305Z 0 [ERROR] InnoDB: Cannot open datafile './ibdata1'
2023-03-22T05:50:50.040311Z 0 [ERROR] InnoDB: Could not open or create the system tablespace. If you tried to add new data files to the system tablespace, and it failed here, you should now edit innodb_data_file_path in my.cnf back to what it was, and remove the new ibdata files InnoDB created in this failed attempt. InnoDB only wrote those files full of zeros, but did not yet use them in any way. But be careful: do not remove old data files which contain your precious data!
2023-03-22T05:50:50.040316Z 0 [ERROR] InnoDB: InnoDB Database creation was aborted with error Cannot open a file. You may need to delete the ibdata1 file before trying to start up again.
2023-03-22T05:50:50.641211Z 0 [ERROR] Plugin 'InnoDB' init function returned error.
2023-03-22T05:50:50.641243Z 0 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2023-03-22T05:50:50.641256Z 0 [ERROR] Failed to initialize builtin plugins.
2023-03-22T05:50:50.641264Z 0 [ERROR] Aborting
2023-03-22T05:50:50.641291Z 0 [Note] Binlog end
2023-03-22T05:50:50.641384Z 0 [Note] Shutting down plugin 'CSV'
2023-03-22T05:50:50.641402Z 0 [Note] Shutting down plugin 'MyISAM'
2023-03-22T05:50:50.642273Z 0 [Note] /export/servers/mysql/bin/mysqld: Shutdown complete



但是,當然,如果你在系統啟動檔案並用守護行程的方式啟動 mysqld ,那麼你無法在命令列中看到這些錯誤資訊。

[root@exps-test2 ~]# /export/servers/mysql/bin/mysqld_safe --defaults-file=/export/restore/tool/general_mysql_backup_extract_tool/mysql-5.cnf --user=mysql --datadir=/export/restore/
Logging to '/export/restore/exps-test2.err'.
2023-03-22T05:53:47.138456Z mysqld_safe Starting mysqld daemon with databases from /export/restore
2023-03-22T05:53:47.347547Z mysqld_safe mysqld from pid file /export/restore/exps-test2.pid ended



在這種情況下,需要檢查錯誤紀錄檔檔案中的資訊,或者,如果沒有任何錯誤紀錄檔檔案,那麼需要檢查作業系統紀錄檔中有關mysqld相關的訊息。

開啟或關閉一個特定功能的時候。例如,關閉特性的選項。

InnoDB引擎啟動失敗的時候,雖然伺服器成功啟動,但是InnoDB引擎並沒有成功載入。

如果SQL模式不包含 NO_ENGINE_SUBSTITUTION,我們仍然能夠成功建立引擎為InnoDB的表:

mysql> CREATE TABLE t1(f1 int) ENGINE=InnoDB;
Query OK, 0 rows affected, 2 warnings (0.03 sec)



我們需要檢查上面的警告資訊,在這個例子中,我們在建立表的時候使用了錯誤的儲存引擎,因此我們在嘗試啟動 InnoDB 引擎的時候發生了錯誤:

mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------+
| Level   | Code | Message                                    |
+---------+------+--------------------------------------------+
| Warning | 1286 | UnKnown table engine 'InnoDB'              |
+---------+------+--------------------------------------------+
| Warning | 1266 | Using storage engine MyISAM for table 't1' |
+---------+------+--------------------------------------------+



所以如果某個依賴的功能出現問題,該功能是否存在於伺服器範例上。而錯誤訊息清楚的說明了問題出在哪裡。

可更改伺服器執行方式的變數

這種型別的變數會影響 MySQL 伺服器如何處理使用者的輸入,舉一個簡單的例子來清楚地說明設這種這種型別的變數而帶來的效果。在這個例子中,將SQL模式設定為STRICT_TRANS_TABLES使無效資料插入事務性表的嘗試被拒絕,而不是被忽略。

有關硬體資源限制的選項

本分類中的設定選項能夠對硬體資源的利用施加限制。它們通常有兩個用途:優化效能及限制某此操作。當你希望對使用者端與伺服器之間的流量施加一些限制,或者防止拒絕服務攻擊時,剛才提到的兩種用途中,後者對該場景非常有用。它能更好地讓特定使用者得到更優雅的錯誤,因為資源不足要好過 mysqld 程序終止,因為 mysqld 程序終止後便不能處理所有傳入的請求。

使用--no-defaults 選項

檢查 MySQL 伺服器是否沒有指定選項是較容易的,即,如果它的選項全部使用預設值如果你對於mysqld如何在未設定自定義選項的場景下執行有一個粗略的猜測,那麼你就可以使用--no-defaults 選項啟動 MySQL 伺服器並與你設定了自定義選項的情況進行比較

效能選項

這一類選項通常不會引發錯誤,但它們有可能對伺服器的效能產生巨大的影響。通常可以在不同的真實負載的生產伺服器上調整這些選項,直到找到一個適合特定環境的效能選項設定組合。

然而,當你選擇了這些選項的時候,有一種可能出現的情況會導致錯誤,所以從組態檔中移除或降低效能設定選項的權重是有意義的。這個場景是:你的伺服器遇到一個資源不足錯誤。最常見的情況涉及缺少記憶體或者檔案描述符。如果伺服器存在此類問題,可以使用--no-defaults 辦法來找明設定了太大的選項。

二、整體優化思路

欲速則不達

調整 MySQL 伺服器的時候,至少是當你無法 100%確定你知道自己在做什麼的時候。

這意味著,如果你認為一組設定選項可以改變 MySQL 伺服器的行為,並使它更好地為你的應用程式提服務,那麼你可以改變一個選項,然後進行測試,如果結果是有效的,那麼你可以繼續新增其他選項,以此類推,直到你已經檢查完畢每一個相關選項。這可能是一個很緩慢的過程,但如果在這一過程中發生錯誤,你可以放心的回滾到本次變化之前,並能夠迅速地讓你的伺服器回到工作狀態。

在你調整記憶體緩衝區或者其他選項以限制對硬體資源的利用時,這種方式是非常重要的。但這種方式也同樣能夠用於伺服器行為設定選項的修改。即使你對變數到底在做什麼有著良好的認知,這也僅僅能讓你可以更容易地發現和修復某個錯誤,而不是在幾十種選項擇中找出錯誤的根源。

當你在使用該方法的時候,需要儲存每一個測試結果。例如,如果你正在嘗試提升伺服器的效能,那麼你需要執行基準測試或測試查詢執行時間在設定選項改變前後的變化,然後重複同樣的測試,再去修改每個選項。

通過基準測試迭代優化

你也許期望 (或者相信自己會期望) 通過建立一套基準測試方案,然後不斷迭代地驗證對設定項的修改來找到最佳設定方案。通常我們都不建議大家這麼做。這需要做非常名的工作和研究,並且大部分情況下潛在的收益是非常小的,這可能導致巨大的時間浪費而把時間花在檢查備份、監控執行計劃的變動之類的事情上,可能會更有意義。

即使更改一個選項後基準測試出現了提升,也無法知道長期執行後這個變更會有什麼副作用。基準測試也不能衡量一切,或者沒有執行足夠長的時間來檢測系統的長期穩定性修改就可能導致如週期性效能抖動或者週期性的慢查詢等問題。這是很難察覺到的。

有的時候我們執行某些組合的基準測試,來仔細驗證或壓測伺服器的某些特定部分,使得我們可以更好地理解這些行為。一個很好的例子是,我們使用了很多年的一些基準測試,用來理解InnoDB 的重新整理行為,來尋找更好的重新整理演演算法,以適應多種工作負載和多種硬體型別。我們經常測試各種各樣的設定,來理解它們的影響以及怎麼優化它們。但這不是一件簡單的事一一這可能會花費很多天甚至很多個星期一一而且對大部分人來說這沒有收益,因為伺服器特定部分的認識侷限往往會掩蓋了其他問題。例如,有時我們發現,特定的設定項組合,在特定的邊緣場景可能有更好的效能,但是在實際生產環境這些設定項並不真的合適,例如,浪費大量的記憶體,或者優化了吞吐量卻忽略了崩潰恢復的影響。

如果必須這樣做,我們建議在開始設定伺服器之前,開發一個客製化的基準測試包。你必須做這些事情來包含所有可能的工作負載,其至包含一些邊緣的場景,例如很龐大很複雜的查詢語句。在實際的資料上重放工作負載通常是一個好辦法。如果已經定位到了一個特定的問題點一一例如一個查詢語句執行很慢一一也可以嘗試專門優化這個點,但是可能不知道這會對其他查詢有什麼負面影響。

最好的辦法是一次改變一個或兩個變數,每次一點點,每次更改後執行基準測試,確保執行足夠長的時間來確認效能是否穩定。有時結果可能會令你感到驚訝,可能把一個變數調大了一點,觀察到效能提升,然後再調大一點,卻發現效能大幅下降。如果變更後效能有隱患,可能是某些資源用得太多了,例如,為緩衝區分配太多記憶體、頻繁地申請和釋放記憶體。另外,可能導致 MySQL 和作業系統或硬體之間的不匹配。例如,我們發現 sort_buffer_size的最佳值可能會被 CPU 快取的工作方式影響,還有 read_buffer_size需要伺服器的預讀和 I/O 子系統的設定相匹配。更大並不總是更好,還可能更糟糕。一些變數也依賴於一些其他的東西,這需要通過經驗和對系統架構的理解來學習。

三、優化設定

影響伺服器與使用者端行為的選項

伺服器相關選項

這些選項影響所有的連線與語句。

限制與 max_ 變數*

如果你發現mysqld限制了你傳送語句或返回結果的大小,你只須檢查它們的值。

•許可權

如果語句失敗,你的使用者是否有執行它的許可權,或特定資料庫或者表的許可權。

•SQL模式

當遇到「奇怪」的查詢結果時,請檢查 SQL 模式並分析它是否影響查詢。

•字元集與排序規則

每當你懷疑某些關於字元集與排序規則的事情有錯誤時,請執行以下兩個查詢,然後分析查詢結果與上下文。

mysql> SHOW VARIABLES LIKE '%char%';
mysql> SHOW VARIABLES LIKE '%coll%';



通常的安全規則是獲取所有的 character_set_* 變數、 collation_* 變數,並且建立選項相同的任何表與一起協同的連線。設定使用者端選項最簡單方式使用 SET NAMES 語句。

當在排序或者比較過程中遇到問題時,請檢查字元集選項與表的定義。

•作業系統處理 lower_case* 引數

lower_case_filesystem 與 lower_case_table_names 選項跟字元集選項的作用非常相似。這些變數確定作業系統如何處理資料庫物件的大小寫情況。

最好不要修改它們的值,特別是作業系統不區分大小寫時。

•初始 SQL

這些選項確定伺服器在不同的時間是否應該自動執行某些 SQL 語句

init_file

如果指定,此變數將命名一個檔案,其中包含在啟動過程中要讀取和執行的 SQL 語句。每條語句必須在一行中,並且不應包含註釋。

init_connect

伺服器為每個連線的使用者端執行的字串。該字串由一個或多個 SQL 語句組成,以分號字元分隔。

init_slave

該變數類似於init_connect,但是是一個字串,每次複製 SQL 執行緒啟動時由副本伺服器執行。字串的格式與變數的格式相同init_connect。該變數的設定對後續START SLAVE語句生效。

open_files_limit

這個重要選項限制 MySQL 伺服器同時開啟檔案控制程式碼的數量。限制數量越高,開啟的表檔案與臨時表越多,因此處理的並行連線量數越多。如果這個限制在你的環境中設定得太低,在你試圖連線、開啟一個表或者執行一個需要建立臨時表的查詢時就會出現錯誤。

log_warnings

是否向錯誤紀錄檔生成額外的警告訊息。

當此選項開啟(非零)時,就會在伺服器的錯誤紀錄檔檔案中寫人警告資訊。它們不是在 SOL 執行期間發出的警告,而是顯示伺服器內到底是怎麼回事的偵錯訊息。如果設定為 2,此選項告訴伺服器記錄連線錯誤。當你正在對使用者端無法連線或正在失去連線的情況做故障排除時,這非常重要。紀錄檔並非總是能找到問題所在,但其警告訊息往往對要做什麼能給出一些啟發。當使用同步複製時,在主伺服器上開啟此選項非常重要,因為你能確定從伺服器 IO 執行緒何時失去連線。反過來它是網路故障的一種症狀,這在將來可能導致更嚴重的問題。

當在從伺服器上設定為 1(預設值) 時,它將輸出自己的診斷訊息,例如:在二進位制紀錄檔和中繼紀錄檔中的位置及其複製狀態。從 5.1.38 版本開始,在基於語句模式的同步複製中,需要啟用此選項,以便在從伺服器輸出不安全語句的資訊。( 5.1.38版本之前,從伺服器在任何情況下都會輸出此類訊息。) 從 5.1.38 版本開始,可以關閉此選項( 設定為 0),來丟棄你確定不需要該訊息的紀錄檔。

log_error_verbosity

伺服器將錯誤、警告和註釋訊息寫入錯誤紀錄檔的詳細程度。下表顯示了允許的值。預設值為 3。

log_error_verbosity value 允許的訊息
1 錯誤訊息
2 錯誤和警告訊息
3 錯誤、警告和資訊訊息

log_error_verbosity在 MySQL 5.7.2 中新增。它優於舊的系統變數,應該使用它來代替舊的log_warnings系統變數。log_warnings有關該變數如何與 相關的資訊,請參閱 的描述log_error_verbosity。特別是,賦值給log_warnings賦值給log_error_verbosity,反之亦然。

複製選項

這些選項確定了主從伺服器之間的關係。

•binlog-* 與 replicate-* 過濾器

通過 binlog-do-、 replicate-do-、 binllog-ignore-* 與 replicate-ignore-* 選項,在複製過程中, MySQL有能力過濾物件。 binlog-* 選項減少在主伺服器上寫入二進位制紀錄檔檔案的事件,而 replicate-* 指定在從伺服器上記錄到二進位制紀錄檔。從伺服器還有replicate-wild-do-* 與 replicate- wild-ignore* 選項,二者允許通過模式匹配,指定哪些應該或哪些不應該同步。

•二進位制紀錄檔格式a. binlog_format

變數允許你選擇複製的格式:STATEMENT、ROW、或MIXED。這是一個動態變數,它能在 SESSION 級別調整。

binlog_direct_non_transactional_updates

此選項指定何時非事務表更新應該寫入二進位制紀錄檔。

預設情況下,當使用事務時,MySQL將非事務表的更新寫入事務快取裡,僅當事務提交後,才把快取重新整理到二進位制紀錄檔裡。這樣做以便從伺服器更有可能與主伺服器資料最終一致,即使依賴事務表中的資料來更新非事務表,並且主伺服器在許多並行執行緒中同步更新相同的表。

這是一個動態變數,可以在 SESSION 級別改變它,所以,可以在特定語句下使用它。它的工作原理決定了它只能在基於語句模式的複製中オ生效。

log_bin_trust_function_creators

這個選項告訴 mysqld 當用戶沒有 SUPER 許可權卻試圖建立一個不確定的函數時,不要觸發警告。

•binloig_cache_size 與類似選項

此條目包括以下選項:

binlog_cache_size

binlog_stmt_cache_size

max_binlog_cache_size

max_binlog_stmt_cache_size

在寫入二進位制紀錄檔之前,這些快取儲存在事務期間提交的事務與非事務語句。如果一個事務需要超過這個位元組數的記憶體,伺服器會生成一個 「Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage」 錯誤。

檢查 Binlog_cache_useBinlog_stmt_cache_useBinlog_cache_disk_useBinlog_stmt_cache_disk_use狀態變數來找出 binlog快取使用的頻率以及事務大小超過Binlog_cache_useBinlog_stmt_cache_use的頻率。當事務大小操作快取大小時,將會建立臨時表來儲存事務快取。

slave_skip_errors

此選項允許從伺服器SOL執行緒即使遇到某類錯誤時還能執行。例如,主伺服器執行在寬鬆的 SQL 模式而從伺服器卻有一個嚴格的SQL模式,當插入字串到整數位段時,由於資料格式不一致,而報告1366( ERROR1366(HY000): Incorrect integer value)錯誤,可以設定 slave skip errors ,以便從伺服器不會出現故障。

這個選項可能導致主伺服器從伺服器資料不一致而又很難診斷,所以,如果你遇到這樣的問題,請檢查該選項是否沒有設定。

read_only

該選項使從伺服器伺服器唯讀。這意味著,僅僅只有從庫SQL執行緒才能更新其資料,而其他連線只能讀資料。該選項對於保持從伺服器資料的一致很重要。然而,這個選項並不能限制具有 SUPER 許可權的使用者更改表。另外,所有使用者仍允許建立臨時表。

super_read_only

該選項使伺服器甚至禁止擁有 SUPER 。

引擎選項

本節主要介紹 InnoDB 相關選項。

innodb_autoinc_lock_mode

該選項用於生成自動增量值的鎖定模式。

innodb_file_per_table

Innodb預設在共用表空間中存放表和索引資料。使用此選項,你可以告知它將表的索引和資料存放在單獨的檔案裡。共用表空間仍然用來存放表定義。此選項在設定後建立的表上生效;之前建立的表依然使用共用表空間。

innodb_table_locks

此變數定義了 InnoDB 是如何處理 LOCK TABLES 語句發出的表鎖請求。預設(當設定了這刻返回並且內部將表鎖住。當關閉時(設定為0),它會接收 LOCK TABLE 語句,執行緒直到所有鎖釋放後才從 LOCK TABLES ...WRITE返回。

innodb_lock_wait_timeout

這是 InnoDB 等待行鎖直到放棄的秒數。在 innodb_lock_wait_timeout秒後,它會返回錯誤 「ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction」 至使用者端。我經常看到人們將這個變數設得很大來防止查詢失敗,這隻會導致更嚴重的問題,因為許多阻塞的事務會互相鎖住。嘗試在應用程式層處理鎖等待錯誤,並不要將它設定得過高。此引數的最佳值取決於應用程式,通常應該大約為正常事務所消耗的時間。它的預設值是50秒,對於需要立即返回結果的應用程式有些大。

innodb_rollback_on_timeout

當査詢因鎖等待錯誤而中斷時,只有最後一條語句回滾了,整個事務還沒有中止。如果將選項設定為1你將會改變此行為。這種情況下事務會在鎖等待超時後立刻回滾。

innodb_use_native_aio

指定 InnoDB 是否應該使用 Linux下原生的AIO介面,或者是自己來實現,稱作 「模擬AIO「。如果設定 innodb_use native_aio,lmoD將分發IO請求至核心。這提高了可延伸性因為比起模擬AIO新核心能夠處理更多的並行IO請求。

此選項預設開啟,在正常操作下不應該改變。

執行大量InnoDBI/O 執行緒,尤其是在同一臺伺服器上執行多個此類範例,可能會超出 Linux 系統的容量限制。在這種情況下,您可能會收到以下錯誤:

EAGAIN: The specified maxevents exceeds the user's limit of available events.



您通常可以通過將更高的限制寫入 來解決此錯誤/proc/sys/fs/aio-max-nr

innodb_locks_unsafe_for_binlog

此變數定義 InnoDB如何使用間隙鎖來搜尋和掃描索引。預設值(設為0)下,間隙鎖開啟。如果設為1,大多數操作下會禁用間隙鎖。其工作原理類似於隔離級別中的 READ COMMITTED,但由於不太好調節應儘量避免。即使它允許你來處理鎖問題,當並行事務插入新行至間隙時它也會帶來新的問題。所以推薦用 READ COMMITTED替代它。這個變數不能設定為 SESSION 級別,它會彩響所有事各

連線相關的選項

超時

innodb_lock_wait_timeout

這是 InnoDB 等待行鎖直到放棄的秒數。在 innodb_lock_wait_timeout秒後,它會返回錯誤 「ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction」 至使用者端。我經常看到人們將這個變數設得很大來防止查詢失敗,這隻會導致更嚴重的問題,因為許多阻塞的事務會互相鎖住。嘗試在應用程式層處理鎖等待錯誤,並不要將它設定得過高。此引數的最佳值取決於應用程式,通常應該大約為正常事務所消耗的時間。它的預設值是50秒,對於需要立即返回結果的應用程式有些大。

lock_wait_timeout

它適用於後設資料鎖。這個鎖對所有需要後設資料鎖的操作有效:DML(資料操縱語言語句,如 INSERT、 UPDATE和 DELETE),DDL、LOCKTABLES等。預設值是3153600秒,也就是一年。所以預設情況下,有效MDL鎖永遠不會解除。然而,可以更改值為大於1秒的任何值。它是一個動態變數,可以在SESSION級別更改。

connect_timeout

這個超時使用在 MySQL伺服器在響應之前等待連線封包的秒數。從5.1版本開始,此值預設設定為10秒。

interactive_timeout

伺服器在關閉互動式連線之前等待其活動的秒數。

wait_timeout

在斷開連線前等待任何使用者端中活動的時間。如果使用者端是互動式的並且 interactive_timeout的值不同於wait_timeout,則以 interactive_timeout為準。

max_connect_errors

來自主機的連續連線請求在沒有成功連線的情況下被中斷後max_connect_errors,伺服器阻止該主機進一步連線。如果在先前的連線中斷後,在少於max_connect_errors嘗試次數的時間內成功建立了來自主機的連線,則主機的錯誤計數將被清除為零。要取消阻止被阻止的主機,請重新整理主機快取。

max_connections

允許的最大並行使用者端連線數。最大有效值是的有效值和實際設定的值中的較小者。

skip_name_resolve

檢查使用者端連線時是否解析主機名。如果這個變數是OFFmysqld 在檢查使用者端連線時解析主機名。如果是ONmysqld 只使用 IP 號碼;在這種情況下,Host授權表中的所有列值都必須是 IP 地址。

net_read_timeout

從使用者端寫入 MySQL伺服器等待應答的時間。例如,此超時會在使用者端執行大的插入操作時起作用。

net_write_timeout

使用者端從伺服器中讀取時等待應答的時間。例如,當用戶端傳送一個 SELECT查詢讀取結果,如果使用者端等待一段時間未收到資料,這個超時會斷開此連線。如果使用者端需要在處理結果前做一些工作,檢查工作的持續時間是否長於這個超時。

與安全相關的選項

--skip-grant-tables

--skip-grant-tables導致伺服器不讀取mysql系統資料庫中的授權表,從而在根本不使用特權系統的情況下啟動。這使任何有權存取伺服器的人都可以不受限制地存取所有資料庫。

--safe-user-create

不允許使用GRANT語句來建立使用者,除非使用者有mysql.user 表的INSERT許可權才可以。

secure_auth

如果啟用此變數,則伺服器會阻止嘗試使用以舊(4.1 之前)格式儲存密碼的帳戶的使用者端連線。啟用此變數以防止所有使用舊格式的密碼(因此通過網路進行不安全的通訊)。

此變數已棄用;希望在未來的 MySQL 版本中將其刪除。它始終處於啟用狀態,嘗試禁用它會產生錯誤。

secure_file_priv

限制LOAD FILE函數以及LOAD DATASELECT… INTO OUTFILE語句只能使用指定目錄。

與效能相關的選項

緩衝區和最大值

join_buffer_size

這是為連線操作分配的最小快取大小,這些連線使用普通索引掃描、範圍掃描,或者連線不使用索引。兩表之間進行全連線時分配快取。因此,連線兩個表的一條查詢分配一塊快取,連線3個表的一個分配兩塊查詢快取,以此類推。這個選項可在 SESSION級使用,能對於特定連線設定。

為了查出是否需要增加join_buffer_size,可以檢查 Select_scan狀態選項,它包括第一張表執行完整掃描的連線數量,同樣 Select_ full_range_ join,它包含使用範圍搜尋的連線數量。這些狀態變數的值不會隨著 join buffer size的值的變化而變化,這樣你可以利用它們來查出是否需要大的 join buffer size,而不是衡量該值改變後的有效性

net_buffer_length

伺服器在使用者端連線後立刻建立的快取大小,用來儲存請求和結果。根據需要這個大小可以增長至 max_allowed_packet正常情況下不用改變預設值(16384位元組),但當設定 max_connections選項時要記住此值。

query_prealloc_size

此快取為語句解析和執行而分配。語句間快取是不釋放的。如果執行復雜查詢,增加快取是合理的,這樣 mysqld不會在執行查詢的時候在分配記憶體上耗時。增加此大小到最大查詢的位元組數。

read_buffer_size

該變數是MySQL讀入緩衝區大小。對錶進行順序掃描的請求將分配一個讀入緩衝區,MySQL會為它分配一段記憶體緩衝區。read_buffer_size變數控制這一緩衝區的大小。如果對錶的順序掃描請求非常頻繁,並且你認為頻繁掃描進行得太慢,可以通過增加該變數值以及記憶體緩衝區大小提高其效能。

read_rnd_buffer_size

此變數用來控制在排序和傳送結果至使用者端之間存放讀取結果的大小。大的值能提高包含ORDER BY的查詢的效能。

sort_buffer_size

每個執行緒需要排序的時候會分配此快取。查明你是否需要增加此快取的大小,檢查 ort merge_ passes狀態變數。也可以檢查查明你執行了多少個排序操作。sort_rangesort_rowssort_scan來這些狀態變數顯示了排序操作的數量。

為了找出快取合適的大小,需要檢查一條或多條查詢排序的行數,並乘以行大小。或者簡單地設定不同的值直到sort_merge_passes停止增長。

sort_buffer_size快取經常會分配,所以大的 GLOBAL值會降低效能而不是增加效能。因此,最好不要設定此選項為 GLOBAL變數,而是當需要時使用 SET SESSION增加它。

sql_buffer_result

如果啟用,則sql_buffer_result強制將語句的結果SELECT放入臨時表中。這有助於 MySQL 儘早釋放表鎖,並且在需要很長時間才能將結果傳送到使用者端的情況下非常有用。預設值為OFF

為了找出查詢是否在傳送結果集上消耗過多時間,執行 SHOW PROCESSLIST來檢查查詢在「 Sending data」狀態下的時間。

thread_cache_size

為將來使用快取起來的執行緒數量。當一個使用者端斷開連線時,通常其執行緒也被銷燬。如果該選項設定為正值 N,那麼連線斷開後 N個執行緒將被快取起來。在具有良好執行緒實現的系統上,該選項不能顯著地提高效能,但是,對於一個應用使用成百上千連線的情況,還是很有用的。

thread_stack

每個執行緒的棧大小。如果該變數設定過小,將會限制SQL語句的複雜性、儲存過程的遞迴深度,以及伺服器上其他記憶體消耗型的操作。對於大部分安裝來說,預設值(32位元系統是192KB;64位元系統是256KB)就可以。如果類似"Thread stack overrun"的錯誤訊息,請增大該引數。

tmp_table_size

記憶體中,內部臨時表的最大值。伺服器預設設定為max_heap_table_sizetmp_table_size二者中的最小值。如果你有足夠的記憶體,並且Created_tmp_disk_tables狀態變數在增大,請增大該變數。把需要臨時表的所有結果集放在記憶體中,可以大大提高效能。

query_cache_size

MySQL伺服器儲存查詢及其結果集的快取大小。預設情況下,查詢快取是禁用的。於5.7.20版本之後棄用。

table_definition_cache

儲存在快取中的表定義的數量。當表數量很大時,可以增大該值。如果需要,可以調整該值,以便最近的表重新整理( FLUSH TABLES)後,保持 Opened_table_definitions於或等於Open_table_definitions

table_open_cache

儲存在快取中的表描述符的數量。調整該值,以便 Opened_tables仍小於或等於Open_tables

控制優化器的選項

這些變數可以在 SESSION 級別設定,所以,你可以實驗它們是怎樣影響特點查詢的。

optimizer_prune_level

如果該變數設為on,優化器刪除即時搜尋發現的不太有效的計劃;如果設定為off,優化器使用詳盡的搜尋。預設值為1(on)。如果你懷疑優化器選擇的不是最優計劃,你可以改變它的值。

optimizer_search_depth

優化器搜尋的最大深度。該值越大,優化器越有可能為複雜的查詢找到最優計劃。提高該值的代價就是優化器在搜尋計劃時的時間開銷增大。如果設定為0,伺服器會自動選擇一個合理的值,預設值為62(最大值)

optimizer_switch

該變數變數可以控制優化器的行為。

index_merge

啟用或禁用索引合併優化,該優化幾個從合併掃描中獲取行記錄,並把結果合併為一條記錄。在 EXPLAIN的結果輸出中,Merge列顯示的就是這個選項。

index_merge_intersection

啟用或禁用索引合併交叉存取演演算法

當 where從句包含key表示的範圍條件並且與AND關鍵字時,將會使用該演演算法。

如:key_coll < 10 AND key_col2 = 'foo'

使 key_col2 = 'foo' 得到唯一值,優化器也把它當做範圍條件

index_merge_union

啟用或禁用索引合併聯合存取演演算法,當 where從句包含 key 表示的範圍條件和OR關鍵字時,會用到該演演算法。

如:key_col1 = 'foo' OR (key_co12 = 'bar' AND key_col3 ='baz')

index_merge_sort_union

啟用或禁用索引合併排序聯合存取演演算法,當 where從句包含key表示的範圍條件和OR關鍵字時,將使用該演演算法,但是,不會應用索引合併聯合存取演演算法,如(key coll >10 OR key co12 ='bar)AND key co13

max_join_size

對於估計可能超過一定限制的 select 語句,(該選項)阻止優化器進行優化(如檢視多於 max_join_size 的行記錄 )。當偵錯找出沒有使用索引的查詢時,該選項會有很大幫助。

max_length_for_sort_data

當無法使用索引時,如果對 ORDER BY 進行條件優化,MySQL 將使用檔案排序演演算法。該演演算法有兩個變體。原始演演算法讀取所有匹配的行記錄,在快取裡儲存戰對的鍵值和行指標,該快取大小受 sort_buffer_size 限制。快取中的值排序後,該演演算法再次讀取表記錄,但是,這次按照一定順序讀取。該演演算法的缺點是兩次讀取行記錄。

改進後的方法是讀取整個行記錄到緩衝區,然後排序鍵值,從緩衝區中讀取行記錄。該方法的問題是結果集通常超過sort_buffer_size,所以,對於巨量資料集,磁碟I/O 操作使得該演演算法很慢。max_length_for_sort_data 變數限制鍵值和行記錄指標對的大小,因此原始演演算法適用於鍵值和行指標對中額外列的總大小超過了該限制的情況。

磁碟活動多,並且 CPU 活動少是需要調低該變數的一個訊號。

max_seeks_for_key

根據表掃描必須檢查的記錄行數量,為使用鍵值而不是表掃描設定閾值。設定該引數為一個較小的值,比如 100,在表掃描時,可以強制優化器優先檢視索引。

max_sort_length

設定對 BLOB 或 TEXT 值排序時用到的初始位元組數,後面的部分將被忽略。

與引擎相關的選項

innodb_adaptive_hash_index

自適應InnoDB雜湊索引是啟用還是禁用。根據您的工作負載,可能需要動態啟用或禁用自適應雜湊索引以提高查詢效能。由於自適應雜湊索引可能並非對所有工作負載都有用,因此在啟用和禁用它的情況下使用實際工作負載進行基準測試。

innodb_additional_mem_pool_size

InnoDB 用來儲存資料字典資訊和其他內部資料結構的記憶體池的大小。在 MySQL 5.7.4 中刪除。

innodb_autoinc_lock_mode

用於生成 自動增量值的 鎖定模式 。允許的值為 0、1 或 2,分別表示傳統、連續或交錯。預設設定為 1(連續)。

innodb_buffer_pool_size

InnoDB 為儲存資料、索引、表結構、自適應雜湊索引等分配的記憶體大小,這是影響 innodb 效能最重要的選項。可以將其設定為實體記憶體的 80%。理想情況下,該緩衝區足夠大,以致可以包含所有活動的 InnoDB 表和額外空間。同時,也要把其他緩衝區計算在內,尋找一個好的平衡。

匹配Innodb buffer pool %的,狀態變數顯示 InnoDB 緩衝池的當前狀態。

該變數的設定需要經過實際環境中非常嚴謹的驗證。

innodb_buffer_pool_instances

該選項設定 InnoDB 緩衝池應切分的範例數量。每個範例有它自己的空閒列表、重新整理列表、使用LRU演演算法的儲存物件的列表,以及其他資料結構,並且受到自身互斥體的保護。設定該變數大於 1,可以提高大型系統的並行效能。每個範例的(緩中區)大小是 innodb_buffer_pool_size/innodb_buffer_pool_instances,並且至少是1GB。如果 innodb_buffer_pool_size小於 1GB,該選項不生效。

innodb_buffer_pool_instances 切分緩衝區互斥體,所以,如果有 8個或者更多並行SESSION 同時存取 InnoDB 緩衝池,該選項可以設定為 4~16。該選項取決於innodb_buffer_pool_size值和可用的記憶體。

innodb_checksums

預設情況,InnoDB 使用校驗和驗證磁碟上所有頁。該選項可以立即確定資料檔案是否由於磁碟壞軌或者其他原因而損壞。通常需要開啟該功能,但是,在很少的情況下,當不關心資料時( 比如,唯讀從伺服器,不提供(線上) 服務,只做備份 ),關閉該功能,可以提升效能。innodb_checksums已棄用,替換為innodb_checksum_algorith

innodb_checksum_algorithm

指定如何生成和驗證儲存在InnoDB表空間的磁碟塊中的校驗和。

innodb_commit_concurrency

可以同時提交事務的執行緒數量,預設值為 0( 沒有限制 )。

innodb_thread_concurrency

InnoDB 內部同時執行的執行緒數量,不要把它和 MySQL 伺服器建立的連線執行緒的數量混淆。預設值是 0:不限制並行或不檢查並行。

儘管大量執行緒並行執行一般意味著高效能,但是,如果同時並行執行很多使用者對談,你可能遇到互斥體爭用,如果同時執行的使用者執行緒不超過 16 個,通常不用擔心該引數。如果有更多使用者 SESSION,可以通過查詢 Performance Schema 或者SHOW ENGINE INNODBMUTEX 來監控互斥鎖。

如果出現互斥體爭用,可以嘗試限制該變數為 16 或 32,或者把 mysqld 程序放置到 Linux 的任務集裡或者 Solaris 的處理器集裡,同時限制它為更少的核心而不是所有核心。

innodb_concurrency_tickets

當允許一個執行緒進人InnoDB 時,它接收 innodb_concurrency_tickets張並行「票」( ticket),這些票允許執行緒離開和重新進人 InoDB,直到它使用完這此票。

預設值是 500。用完這些票後,把執行緒放置到等待佇列中,以獲取一組新票。

innodb_doublewrite

預設情況下,InnoDB 分兩次儲存資料: 第一次寫人雙寫緩衝,第二次寫人資料檔案。像innodb_checksums一樣,對於資料安全不是最重要的場景,這個安全選項可以關閉 of,以提升效能。

Innodb dblwr_writes 和 Innodb_dblwr pages written 狀態變數分別顯示兩次寫操作的數量和寫頁的數量。

innodb_flush_log_at_trx_commit

定義何時把更改寫人(重做紀錄檔檔案以及重新整理到磁碟。如果設定為 1(預設值)在每個事務提交時更改均會寫人和重新整理到磁碟。為了得到更好的效能,可以設定該值為 0( 每秒寫人紀錄檔檔案和重新整理到磁碟,而每個事務提交時,不做操作)或者2( 每次提交事務時寫人紀錄檔檔案,但是,每秒重新整理到磁碟 。注意,只有該選項為1時才符合 ACID 事務要求的。

Innodb_os_log_fsyncs 狀態變數儲存 fsync() 到紀錄檔檔案的操作次數。Innodb_os_log_pending_writes 包含掛起的 fsync0寫次數。Innodb_log_writesInnodb_os_log_pending_writes分別包含寫入次數和掛起的寫次數。

innodb_flush_method

預設情況下,fdatasync()是用來重新整理資料檔案的,fsync()是用來重新整理紀錄檔檔案到磁碟的,該值可以更改為以下值中的一個:

O_DSYNC

作業系統使用 O_SYNC 開啟和重新整理紀錄檔檔案,同時使用 fsync()重新整理資料檔案

O_DIRECT

作業系統使用 O_DIRECT開啟資料檔案,並且使用 fsync()重新整理資料檔案。更改innodb_flush_method變數的值,或者提升效能或者降低效能,所以,在(生產)環境中,需要謹慎測試它。

innodb_io_capacity

後臺 InnoDB 任務執行的 I/O 活動的上限。對於大多數現代系統來說,預設值 200是個不錯的選擇。但是,可以根據系統的 I/O 吞吐量,調整該值。在快速記憶體上增大該值,才有意義。

innodb_log_buffer_size

InnoDB 用來把紀錄檔檔案寫人磁碟的緩衝區大小。當緩衝區滿時,必須等待紀錄檔重新整理到磁碟上後,才能繼續進行操作。增大該引數,可以減少磁碟 I/O 操作,但是,只有在存在大量事務時,這才有意義。

狀態變數Innodb_log_waits 包含緩衝區因太小而需要的 I/O 等待次數

innodb_log_file_size

每個紀錄檔檔案的大小。大紀錄檔檔案降低檢查點的活動,節省磁碟I/O。但是,大日忐檔案顯著地延緩崩潰恢復過程。從 1MB 到不超過 innodb_buffer_pool_size/ innodb_log_files_in_group 的值是有合理的。所有紀錄檔檔案加起來不能超過 4GB。

最佳實踐是在不同的磁碟上儲存紀錄檔檔案、資料檔案、如果使用的話,還有二進位制紀錄檔檔案,這樣,即使一個裝置故障,也不會同時丟失所有檔案。

innodb_log_files_in_group

紀錄檔組中的紀錄檔檔案數。以迴圈方式寫入檔案。預設(推薦)值為 2。檔案的位置由innodb_log_group_home_dir指定。紀錄檔檔案的組合大小(innodb_log_file_size*innodb_log_files_in_group)最高可達512GB。

innodb_dedicated_server

該變數啟用時,InnoDB自動設定以下變數:

innodb_buffer_pool_size

innodb_redo_log_capacity或者,在 MySQL 8.0.30 之前,innodb_log_file_sizeinnodb_log_files_in_group

innodb_old_blocks_time

非零值可防止緩衝池被僅在短時間內參照的資料填充,例如在完整表掃描期間。增加此值可以提供更多保護,防止全表掃描干擾緩衝池中快取的資料。預設值為1000。

指定插入到舊子列表中的塊在第一次存取後必須停留在那裡的時間(以毫秒為單位),然後才能移動到新子列表。如果值為0,則插入到舊子列表中的塊在第一次存取時會立即移動到新子列表,無論插入後多久進行存取。如果該值大於0,則塊將保留在舊的子列表中,直到在第一次存取後至少幾毫秒發生存取為止。例如,值1000會導致塊在第一次存取後在舊的子列表中停留1秒,然後才有資格移動到新的子列表。

innodb_open_files

僅當使用innodb_file_per_table 時,該變數才有意義。innodb_open_filesInnoDB可以同時開啟的.ibd 檔案的數量。預設值是 300,該值增大到 InnoDB 所有的表的數量是有意義的。

innodb_read_io_threads

InnoDB 讀操作可以使用的 I/O 執行緒數。這些操作處理預讀: I/O 請求以非同步方式將一組頁資料裝進InnoDB 的緩衝池,然後清空和插人緩衝操作。預設值是 4。

innodb_write_io_threads

InnoDB 從緩衝池中寫髒資料的 I/O 執行緒數量。預設值是 4

innodb_stats_method

伺服器在收集索引值的統計資訊時,處理 null 的方式。這會影響索引的基數,優化器因此生成的查詢計劃。

innodb_stats_on_metadata

啟用該變數(預設值),每次執行元資訊語句時,比如,SHOW TABLE STATUS或者 SHOW INDEX,或者當查詢 InnoDB 表的INFORMATION SCHEMA 或統計資料時,InnoDB 都會更新統計資訊。如果啟用該變數,這些查詢將和每次查詢後執行 ANALYZE TABLE 有一樣的效果。如果伺服器頻繁呼叫這些語句或者查詢具有大量表的資料庫時,可以禁用該變數。但是,當禁用該變數時,表統計資料將過時。

innodb_stats_sample_pages

MySQL 優化器用來計算索引分佈統計資訊的抽樣索引頁的數量,例如呼叫ANALYZE TABLE。如果你懷疑基數計算不合理,請增大該值( 預設值是 8)。但是,如果啟用innodb_stats_on_metadata,增大該值,開啟表的時間會增加。

innodb_strict_mode

該變數啟用時,InnoDB在檢查無效或不相容的表選項時返回錯誤而不是警告。

innodb_max_dirty_pages_pct

InnoDB嘗試從緩衝池中重新整理資料,以使髒頁的百分比不超過此值。該變數設定建立了沖洗活動的目標,它不影響沖洗速度。

計算選項的安全值

通過增大緩衝區或最大值,試圖優化伺服器效能時,全面考慮記憶體使用情況是很重要的,大量緩衝區能因「記憶體不足」錯誤而導致伺服器崩潰。這一節將提供一些公式幫助計算是否超出了可用記憶體。這部分不介紹選項本身,可以參考前面的內容或者 MySQL 手冊,獲取詳細介紹。

伺服器級選項

這些選項是 GLOBAL 的,影響所有連線和查詢,一部分是伺服器啟動時分配的,而另部分是後來分配的,比如查詢快取,初始值是 0,(後續)不斷增長,直至最大值。MySQL 伺服器達到所有的限制,分配所有允許的記憶體,會花費很長時間。因此,需要計算 mysqld 獲得的 RAM 大小,和所有的緩衝區大小保證不要超過它。

query_cache_size

innodb_buffer_pool_size

innodb_log_buffer_size

key_buffer_size

使用下面的公式計算需要為這些緩衝區分配多少 RAM(單位是 MB)。

SELECT (@@query_cache_size +@@innodb_buffer_pool_size + @@innodb_log_buffer_size + @@key_buffer_size)/(1024*1024);



伺服器還有限制檔案描述符數量和快取執行緒數量的選項,該計算可以忽略它們,因為分配給它們的記憶體僅僅是系統的一個指標大小乘以分配項的數量,這個數量足夠小,以至於在現代系統上可以忽略。在這裡列舉一下,僅供參考:

thread_cache_size

table_definition_cache

table_open_cache

innodb_open_files

執行緒級選項

這些選項是基於每個執行緒分配(記憶體)的,這樣,伺服器分配 max_connections * sum( thread options )。設定 max_connections 和這些選項,保證實體記憶體總量 -max_connections* sum(thread option) 伺服器級選項大於0。留一些記憶體給第三類選項和後臺操作,這些操作不受這些變數控制。

執行緒級選項列表如下:

net_buffer_length

thread_stack

query_prealloc_size

binlog_cache_size

binlog_stmt_cache_size

使用下面的公式計算需要為它們分配多少記憶體(單位是 MB):

SELECT @@max_connections * (@@global.net_buffer_length + @@thread_stack + @@global.query_prealloc_size + @@binlog_cache_size + @@binlog_stmt_cache_size) / (1024 * 1024)



為特定操作分配的緩衝區

當伺服器執行特殊操作時,根據需要分配的緩衝區。很難計算出分配的記憶體大小。分析查詢,找出哪些需要很多資源,然後像下面這樣計算:

緩衝區大小 * 為特定查詢分配的緩衝區數量 * 並行執行的查詢數量

對於所有變數,這樣計算,求出總和。

只要對於大多數查詢是足夠的,保持這些選項(的值)小一點。如果一個特定查詢需要更多記憶體,只對於這個對談增加這個變數的值。

以下選項針對每個執行緒分配一次(緩衝區):

read_rnd_buffer_size

sort_buffer_size

myisam_mmap_size

myisam_sort_buffer_size

bulk_insert_buffer_size

preload_buffer_size

以下選項針對每個執行緒分配多次(緩衝區):

join_buffer_size

read_buffer_size

tmp_table_size

可以使用以下公式計算 MySQL 為每個選項分配的記憶體的最大數量( 單位是 GB)

# set @join_tables = YOUR_ESTIMATE_PER_THREAD;
# set @scan_tables = YOUR_ESTIMATE_PER_THREAD;
# set @tmp_tables = YOUR_ESTIMATE_PER_THREAD;

SELECT @@max_connections * (@@global.read_rnd_buffer_size +@@global.sort_buffer_size + @@myisam_mmap_size + @@global.myisam_sort_buffer_size + @@global.bulk_insert_buffer_size + @@global.preload_buffer_size + @@global.join_buffer_size * IFNULL(@join_tables,1) + @@global.read_buffer_size * IFNULL(@scan_tables,1) +@@global.tmp_table_size * IFNULL(@tmp_tables, 1)) / (1024 * 1024 * 1024);



這裡給出一個綜合的公式,計算 MySQL 安裝時最多可以使用的記憶體(單位是 GB )

# set @join_tables = YOUR_ESTIMATE_PER_THREAD;
# set @scan_tables = YOUR_ESTIMATE_PER_THREAD;
# set @tmp_tables = YOUR_ESTIMATE_PER_THREAD;

SELECT (@@query_cache_size + @@innodb_buffer_pool_size + @@innodb_log_buffer_size + @@key_buffer_size + @@max_connections * (@@global.net_buffer_length + @@thread_stack + @@global.query_prealloc_size + @@global.read_rnd_buffer_size + @@global.sort_buffer_size + @@myisam_mmap_size + @@global.myisam_sort_buffer_size + @@global.bulk_insert_buffer_size + @@global.preload_buffer_size + @@binlog_cache_size + @@binlog_stmt_cache_size + @@global.join_buffer_size * IFNULL(@join_tables,1) + @@global.read_buffer_size * IFNULL(@scan_tables, 1) +@@global.tmp_table_size * IFNULL(@tmp_tables, 1))) / (1024 * 1024 * 1024)

參考資料

《高效能MySQL》

作者:京東物流 張澤龍

來源:京東雲開發者社群 自猿其說Tech