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 效能綱要是一項用於低階監控 MySQL 伺服器執行的功能。效能綱要會動態遞增配置記憶體,使其記憶體使用量與實際伺服器負載成比例,而不是在伺服器啟動期間配置所需的記憶體。一旦配置了記憶體,除非伺服器重新啟動,否則不會釋放。如需更多資訊,請參閱第 29.17 節,「效能綱要記憶體配置模型」。
伺服器用來管理用戶端連線的每個執行緒都需要一些執行緒特定的空間。以下列表指出這些空間以及控制其大小的系統變數
堆疊(
thread_stack
)連線緩衝區(
net_buffer_length
)結果緩衝區(
net_buffer_length
)
連線緩衝區和結果緩衝區的初始大小都等於
net_buffer_length
位元組,但會根據需要動態擴大到最多max_allowed_packet
位元組。每個 SQL 語句後,結果緩衝區會縮小到net_buffer_length
位元組。當語句執行時,也會配置目前語句字串的副本。每個連線執行緒都會使用記憶體來計算語句摘要。伺服器會針對每個連線配置
max_digest_length
位元組。請參閱第 29.10 節,「效能綱要語句摘要和採樣」。所有執行緒都共享相同的基礎記憶體。
當不再需要執行緒時,分配給它的記憶體將會釋放並返回系統,除非該執行緒返回執行緒快取。在這種情況下,記憶體將保持分配狀態。
每個對資料表執行循序掃描的請求都會配置一個讀取緩衝區。系統變數
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 使用了大量記憶體。這可能是因為不同記憶體位址上的執行緒堆疊所造成的。例如,Solaris 版本的 ps 會將堆疊之間未使用的記憶體計為已使用記憶體。若要驗證這一點,請使用 swap -s
檢查可用的交換空間。我們使用多種記憶體洩漏偵測器(包括商業和開放原始碼)測試 mysqld,因此應該沒有記憶體洩漏。