MySQL 分配緩衝區與快取以提升資料庫作業的效能。預設組態設計為允許 MySQL 伺服器在具有約 512MB RAM 的虛擬機器上啟動。您可以透過增加特定快取與緩衝區相關系統變數的值來提升 MySQL 效能。您也可以修改預設組態,以在記憶體有限的系統上執行 MySQL。
以下清單描述 MySQL 使用記憶體的一些方式。在適用的情況下,會參考相關的系統變數。某些項目為儲存引擎或特定功能專用。
InnoDB
緩衝池是一個記憶體區域,用於保存資料表、索引和其他輔助緩衝區的快取InnoDB
資料。為了高容量讀取作業的效率,緩衝池會劃分為頁面,這些頁面可能保存多個列。為了快取管理的效率,緩衝池實作為頁面的連結清單;不常使用的資料會根據 LRU 演算法的變體從快取中淘汰。如需更多資訊,請參閱第 17.5.1 節,「緩衝池」。緩衝池的大小對於系統效能至關重要
InnoDB
使用malloc()
作業在伺服器啟動時為整個緩衝池分配記憶體。innodb_buffer_pool_size
系統變數定義緩衝池大小。通常,建議的innodb_buffer_pool_size
值為系統記憶體的 50% 到 75%。innodb_buffer_pool_size
可以在伺服器執行時動態設定。如需更多資訊,請參閱第 17.8.3.1 節,「設定 InnoDB 緩衝池大小」。在具有大量記憶體的系統上,您可以透過將緩衝池劃分為多個緩衝池執行個體來提高並行性。
innodb_buffer_pool_instances
系統變數定義緩衝池執行個體的數量。過小的緩衝池可能會導致過度攪動,因為頁面會從緩衝池中清除,但在短時間後又再次需要。
過大的緩衝池可能會因記憶體競爭而導致交換。
儲存引擎介面允許最佳化工具提供有關記錄緩衝區大小的資訊,以用於最佳化工具估計可能讀取多個列的掃描。緩衝區大小可能會根據估計值的大小而有所不同。
InnoDB
使用這種可變大小的緩衝功能來利用列預取,並減少鎖定和 B 樹狀結構導覽的開銷。所有執行緒都會共用
MyISAM
鍵值緩衝區。key_buffer_size
系統變數決定其大小。對於伺服器開啟的每個
MyISAM
表格,索引檔案會開啟一次;資料檔案則會針對每個同時存取該表格的執行緒開啟一次。對於每個並行執行緒,會配置一個表格結構、每個欄位的欄位結構,以及大小為3 *
的緩衝區(其中N
N
是最大列長度,不包括BLOB
欄位)。一個BLOB
欄位需要五到八個位元組加上BLOB
資料的長度。MyISAM
儲存引擎會維護一個額外的列緩衝區以供內部使用。可以將
myisam_use_mmap
系統變數設定為 1,為所有MyISAM
表格啟用記憶體對應。如果內部記憶體臨時表格變得太大(使用
tmp_table_size
和max_heap_table_size
系統變數判斷),MySQL 會自動將表格從記憶體中轉換為磁碟格式,使用InnoDB
儲存引擎。您可以增加允許的臨時表格大小,如 第 10.4.4 節「MySQL 中內部臨時表格的使用」所述。對於使用
CREATE TABLE
明確建立的MEMORY
表格,只有max_heap_table_size
系統變數決定表格可以增長多大,並且不會轉換為磁碟格式。MySQL Performance Schema 是一個用於在低層級監控 MySQL 伺服器執行的功能。Performance Schema 動態地逐步分配記憶體,使其記憶體使用量與實際伺服器負載相符,而不是在伺服器啟動期間分配所需記憶體。一旦分配了記憶體,在伺服器重新啟動之前不會釋放。有關更多資訊,請參閱 第 29.17 節「Performance Schema 記憶體分配模型」。
伺服器用來管理客戶端連線的每個執行緒都需要一些執行緒特定的空間。以下列表指出這些空間以及控制其大小的系統變數:
堆疊 (
thread_stack
)連線緩衝區 (
net_buffer_length
)結果緩衝區 (
net_buffer_length
)
連線緩衝區和結果緩衝區的起始大小都等於
net_buffer_length
位元組,但會根據需要動態擴大到max_allowed_packet
位元組。結果緩衝區在每個 SQL 陳述式之後會縮小到net_buffer_length
位元組。當陳述式執行時,也會配置目前陳述式字串的副本。每個連線執行緒都會使用記憶體來計算陳述式摘要。伺服器會為每個會話配置
max_digest_length
位元組。請參閱 第 29.10 節「Performance Schema 陳述式摘要和取樣」。所有執行緒共用相同的基礎記憶體。
當不再需要執行緒時,分配給它的記憶體會被釋放並返回給系統,除非執行緒返回到執行緒快取中。在這種情況下,記憶體仍會被分配。
每個對表格執行循序掃描的請求都會分配一個讀取緩衝區。
read_buffer_size
系統變數決定緩衝區大小。當以任意順序讀取列時(例如,在排序之後),可能會分配一個隨機讀取緩衝區,以避免磁碟搜尋。
read_rnd_buffer_size
系統變數決定緩衝區大小。所有聯接都在單次傳遞中執行,而且大多數聯接甚至不需要使用臨時表格即可完成。大多數臨時表格都是基於記憶體的雜湊表。具有較大列長度(計算為所有欄位長度的總和)或包含
BLOB
欄位的臨時表格會儲存在磁碟上。大多數執行排序的請求都會分配一個排序緩衝區,以及零到兩個臨時檔案,具體取決於結果集大小。請參閱 第 B.3.3.5 節「MySQL 儲存臨時檔案的位置」。
幾乎所有的解析和計算都是在執行緒本機和可重複使用的記憶體池中完成的。小型項目不需要記憶體額外負擔,因此避免了正常的緩慢記憶體分配和釋放。僅為意外的大型字串分配記憶體。
對於每個具有
BLOB
欄位的表格,緩衝區會動態擴大以讀取更大的BLOB
值。如果您掃描表格,緩衝區會增長到與最大BLOB
值一樣大。MySQL 需要記憶體和描述符才能用於表格快取。所有正在使用的表格的處理程式結構都保存在表格快取中,並以「先進先出」 (FIFO) 的方式管理。
table_open_cache
系統變數定義了初始表格快取大小;請參閱 第 10.4.3.1 節「MySQL 如何開啟和關閉表格」。MySQL 還需要記憶體來用於表格定義快取。
table_definition_cache
系統變數定義了可以儲存在表格定義快取中的表格定義數量。如果您使用大量的表格,可以建立一個大型的表格定義快取,以加快表格的開啟速度。表格定義快取佔用的空間較少,並且不像表格快取那樣使用檔案描述符。FLUSH TABLES
陳述式或 mysqladmin flush-tables 命令會立即關閉所有未使用的表格,並標記所有正在使用的表格,以便在目前執行的執行緒完成時關閉。這有效地釋放了大多數正在使用的記憶體。FLUSH TABLES
在所有表格都關閉之前不會返回。伺服器會由於
GRANT
、CREATE USER
、CREATE SERVER
和INSTALL PLUGIN
陳述式而在記憶體中快取資訊。此記憶體不會被對應的REVOKE
、DROP USER
、DROP SERVER
和UNINSTALL PLUGIN
陳述式釋放,因此對於執行許多導致快取的陳述式實例的伺服器,快取的記憶體使用量會增加,除非使用FLUSH PRIVILEGES
釋放。在複製拓撲中,以下設定會影響記憶體使用量,並且可以根據需要進行調整:
複製來源上的
max_allowed_packet
系統變數會限制來源傳送到其複本以進行處理的最大訊息大小。此設定預設為 64M。多執行緒複本上的系統變數
replica_pending_jobs_size_max
設定了可用於保留等待處理的訊息的最大記憶體量。此設定預設為 128M。記憶體僅在需要時分配,但如果您的複製拓撲有時處理大型交易,則可能會使用它。這是一個軟限制,可以處理更大的交易。複製來源或複本上的
rpl_read_size
系統變數控制從二進位記錄檔案和中繼記錄檔案讀取的最小資料量(以位元組為單位)。預設值為 8192 個位元組。為每個從二進位記錄和中繼記錄檔案讀取的執行緒分配此值大小的緩衝區,包括來源上的傾印執行緒和複本上的協調器執行緒。binlog_transaction_dependency_history_size
系統變數限制了作為記憶體中歷史記錄保存的列雜湊數量。max_binlog_cache_size
系統變數指定單個交易的記憶體使用上限。max_binlog_stmt_cache_size
系統變數指定陳述式快取的記憶體使用上限。
ps 和其他系統狀態程式可能會報告 mysqld 使用大量記憶體。這可能是由不同記憶體位址上的執行緒堆疊引起的。例如,ps 的 Solaris 版本會將堆疊之間未使用的記憶體計為已使用記憶體。要驗證這一點,請使用 swap -s
檢查可用的交換空間。我們使用多種記憶體洩漏偵測器(包括商業版和開源版)測試 mysqld,因此不應存在記憶體洩漏。