mariadb 記憶體佔用優化
本文由雲+社群發表
作者:工程師小熊
摘要:我們在使用mariadb的時候發現有時候不能啟動起來,在使用過程中mariadb佔用的記憶體很大,在這裡學習下mariadb與記憶體相關的配置項,對mariadb進行調優。
查詢最高記憶體佔用
使用以下命令可以知道mysql的配置使用多少 RAM
SELECT ( @@key_buffer_size
+ @@query_cache_size
+ @@innodb_buffer_pool_size
+ @@innodb_additional_mem_pool_size
+ @@innodb_log_buffer_size
+ @@max_connections * ( @@read_buffer_size
+ @@read_rnd_buffer_size
+ @@sort_buffer_size
+ @@join_buffer_size
+ @@binlog_cache_size
+ @@thread_stack
+ @@tmp_table_size
)
) / (1024 * 1024 * 1024) AS MAX_MEMORY_GB;
可以使用mysql計算器來計算記憶體使用
下面是理論,可以直接到推薦配置
如何調整配置
key_buffer_size(MyISAM索引用)
指定索引緩衝區的大小,它決定索引處理的速度,尤其是索引讀的速度。為了最小化磁碟的 I/O , MyISAM 儲存引擎的表使用鍵快取記憶體來快取索引,這個鍵快取記憶體的大小則通過 key-buffer-size 引數來設定。如果應用系統中使用的表以 MyISAM 儲存引擎為主,則應該適當增加該引數的值,以便儘可能的快取索引,提高訪問的速度。
怎麼設
show global status like 'key_read%';
+------------------------+-------------+
| Variable_name | Value |
+------------------------+-------------+
| Key_read_requests | 27813678764 |
| Key_reads | 6798830 |
---------------------
- key_buffer_size通過檢查狀態值Key_read_requests和Key_reads,可以知道key_buffer_size設定是否合理。
- 比例key_reads / key_read_requests應該儘可能的低,至少是1:100,1:1000更好。
show global status like '%created_tmp_disk_tables%';
- key_buffer_size只對MyISAM表起作用。即使你不使用MyISAM表,但是內部的臨時磁碟表是MyISAM表,也要使用該值。可以使用檢查狀態值created_tmp_disk_tables得知詳情。
- 對於1G記憶體的機器,如果不使用MyISAM表,推薦值是16M(8-64M)
另一個參考如下
show global status like 'key_blocks_u%';
+------------------------+-------------+
| Variable_name | Value |
+------------------------+-------------+
| Key_blocks_unused | 0 |
| Key_blocks_used | 413543 |
+------------------------+-------------+
Key_blocks_unused表示未使用的快取簇(blocks)數,Key_blocks_used表示曾經用到的最大的blocks數,比如這臺伺服器,所有的快取都用到了,要麼增加key_buffer_size,要麼就是過渡索引了,把快取佔滿了。比較理想的設定:
- 可以根據此工式來動態的調整
Key_blocks_used / (Key_blocks_unused + Key_blocks_used) * 100% ≈ 80%
show engines;
- 查詢儲存引擎
innodb_buffer_pool_size (innodb索引用)
這個引數和MyISAM的
key_buffer_size
有相似之處,但也是有差別的。這個引數主要快取innodb表的索引,資料,插入資料時的緩衝。為Innodb加速優化首要引數。
該引數分配記憶體的原則:這個引數預設分配只有8M,可以說是非常小的一個值。
- 如果是專用的DB伺服器,且以InnoDB引擎為主的場景,通常可設定實體記憶體的50%,這個引數不能動態更改,所以分配需多考慮。分配過大,會使Swap佔用過多,致使Mysql的查詢特慢。
- 如果是非專用DB伺服器,可以先嚐試設定成記憶體的1/4,如果有問題再調整
query_cache_size(查詢快取)
快取機制簡單的說就是快取sql文字及查詢結果,如果執行相同的sql,伺服器直接從快取中取到結果,而不需要再去解析和執行sql。如果表更改了,那麼使用這個表的所有緩衝查詢將不再有效,查詢快取值的相關條目被清空。更改指的是表中任何資料或是結構的改變,包括INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE等,也包括那些對映到改變了的表的使用MERGE表的查詢。顯然,這對於頻繁更新的表,查詢快取是不適合的,而對於一些不常改變資料且有大量相同sql查詢的表,查詢快取會節約很大的效能。
- 注意:如果你查詢的表更新比較頻繁,而且很少有相同的查詢,最好不要使用查詢快取。因為這樣會消耗很大的系統效能還沒有任何的效果
要不要開啟?
先設定成這樣跑一段時間
query_cache_size=128M
query_cache_type=1
看看命中結果來進行進一步的判斷
mysql> show status like '%Qcache%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 669 |
| Qcache_free_memory | 132519160 |
| Qcache_hits | 1158 |
| Qcache_inserts | 284824 |
| Qcache_lowmem_prunes | 2741 |
| Qcache_not_cached | 1755767 |
| Qcache_queries_in_cache | 579 |
| Qcache_total_blocks | 1853 |
+-------------------------+-----------+
8 rows in set (0.00 sec)
Qcache_free_blocks:表示查詢快取中目前還有多少剩餘的blocks,如果該值顯示較大,則說明查詢快取中的記憶體碎片過多了,可能在一定的時間進行整理。
Qcache_free_memory:查詢快取的記憶體大小,通過這個引數可以很清晰的知道當前系統的查詢記憶體是否夠用,是多了,還是不夠用,DBA可以根據實際情況做出調整。
Qcache_hits:表示有多少次命中快取。我們主要可以通過該值來驗證我們的查詢快取的效果。數字越大,快取效果越理想。
Qcache_inserts: 表示多少次未命中然後插入,意思是新來的SQL請求在快取中未找到,不得不執行查詢處理,執行查詢處理後把結果insert到查詢快取中。這樣的情況的次數,次數越多,表示查詢快取應用到的比較少,效果也就不理想。當然系統剛啟動後,查詢快取是空的,這很正常。
Qcache_lowmem_prunes:該引數記錄有多少條查詢因為記憶體不足而被移除出查詢快取。通過這個值,使用者可以適當的調整快取大小。
Qcache_not_cached: 表示因為query_cache_type的設定而沒有被快取的查詢數量。
Qcache_queries_in_cache:當前快取中快取的查詢數量。
Qcache_total_blocks:當前快取的block數量。
- 我們可以看到現網命中1158,未快取的有1755767次,說明我們這個系統命中的太少了,表變動比較多,不什麼開啟這個功能涉及引數
- query_cache_limit:允許 Cache 的單條 Query 結果集的最大容量,預設是1MB,超過此引數設定的 Query 結果集將不會被 Cache
- query_cache_min_res_unit:設定 Query Cache 中每次分配記憶體的最小空間大小,也就是每個 Query 的 Cache 最小佔用的記憶體空間大小
- query_cache_size:設定 Query Cache 所使用的記憶體大小,預設值為0,大小必須是1024的整數倍,如果不是整數倍,MySQL 會自動調整降低最小量以達到1024的倍數
- query_cache_type:控制 Query Cache 功能的開關,可以設定為0(OFF),1(ON)和2(DEMAND)三種,意義分別如下: 0(OFF):關閉 Query Cache 功能,任何情況下都不會使用 Query Cache 1(ON):開啟 Query Cache 功能,但是當 SELECT 語句中使用的 SQL_NO_CACHE 提示後,將不使用Query Cache 2(DEMAND):開啟 Query Cache 功能,但是隻有當 SELECT 語句中使用了 SQL_CACHE 提示後,才使用 Query Cache
- query_cache_wlock_invalidate:控制當有寫鎖定發生在表上的時刻是否先失效該表相關的 Query Cache,如果設定為 1(TRUE),則在寫鎖定的同時將失效該表相關的所有 Query Cache,如果設定為0(FALSE)則在鎖定時刻仍然允許讀取該表相關的 Query Cache。
innodb_additional_mem_pool_size(InnoDB內部目錄大小)
InnoDB 字典資訊快取主要用來存放 InnoDB 儲存引擎的字典資訊以及一些 internal 的共享資料結構資訊,也就是存放Innodb的內部目錄,所以其大小也與系統中所使用的 InnoDB 儲存引擎表的數量有較大關係。
這個值不用分配太大,通常設定16M夠用了,預設8M,如果設定的記憶體大小不夠,InnoDB 會自動申請更多的記憶體,並在 MySQL 的 Error Log 中記錄警告資訊。
innodb_log_buffer_size (日誌緩衝)
表示InnoDB寫入到磁碟上的日誌檔案時使用的緩衝區的位元組數,預設值為16M。一個大的日誌緩衝區允許大量的事務在提交之前不用寫日誌到磁碟,所以如果有更新,插入或刪除許多行的事務,則使日誌緩衝區更大一些可以節省磁碟IO
通常最大設為64M足夠
max_connections (最大併發連線)
MySQL的max_connections引數用來設定最大連線(使用者)數。每個連線MySQL的使用者均算作一個連線,max_connections的預設值為100。
- 這個引數實際起作用的最大值(實際最大可連線數)為16384,即該引數最大值不能超過16384,即使超過也以16384為準;
- 增加max_connections引數的值,不會佔用太多系統資源。系統資源(CPU、記憶體)的佔用主要取決於查詢的密度、效率等;
- 該引數設定過小的最明顯特徵是出現”Too many connections”錯誤
mysql> show variables like '%max_connect%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| extra_max_connections | 1 |
| max_connect_errors | 100 |
| max_connections | 2048 |
+-----------------------+-------+
3 rows in set (0.00 sec)
mysql> show status like 'Threads%';
+-------------------+---------+
| Variable_name | Value |
+-------------------+---------+
| Threads_cached | 0 |
| Threads_connected | 1 |
| Threads_created | 9626717 |
| Threads_running | 1 |
+-------------------+---------+
4 rows in set (0.00 sec)
可以看到此時的併發數也就是Threads_connected=1,還遠遠達不到2048
mysql> show variables like 'open_files_limit';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| open_files_limit | 65535 |
+------------------+-------+
1 row in set (0.00 sec)
max_connections 還取決於作業系統對單程式允許開啟最大檔案數的限制
也就是說如果作業系統限制單個程式最大可以開啟100個檔案
那麼 max_connections 設定為200也沒什麼用
MySQL 的 open_files_limit 引數值是在MySQL啟動時記錄的作業系統對單程式開啟最大檔案數限制的值
可以使用 show variables like 'open_files_limit'; 檢視 open_files_limit 值
ulimit -n
65535
或者直接在 Linux 下通過ulimit -n命令檢視作業系統對單程式開啟最大檔案數限制 ( 預設為1024 )
connection級記憶體引數(執行緒獨享)
connection級引數,是在每個connection第一次需要使用這個buffer的時候,一次性分配設定的記憶體。
排序效能
mysql對於排序,使用了兩個變數來控制sort_buffer_size和 max_length_for_sort_data, 不象oracle使用SGA控制. 這種方式的缺點是要單獨控制,容易出現排序效能問題.
mysql> SHOW GLOBAL STATUS like '%sort%';
+---------------------------+--------+
| Variable_name | Value |
+---------------------------+--------+
| Sort_merge_passes | 0 |
| Sort_priority_queue_sorts | 1409 |
| Sort_range | 0 |
| Sort_rows | 843479 |
| Sort_scan | 13053 |
+---------------------------+--------+
5 rows in set (0.00 sec)
- 如果發現
Sort_merge_passes
的值比較大,你可以考慮增加sort_buffer_size
來加速ORDER BY 或者GROUP BY 操作,不能通過查詢或者索引優化的。我們這為0,那就沒必要設定那麼大。
讀取快取
read_buffer_size = 128K(預設128K)為需要全表掃描的MYISAM資料表執行緒指定快取
read_rnd_buffer_size = 4M:(預設256K)首先,該變數可以被任何儲存引擎使用,當從一個已經排序的鍵值表中讀取行時,會先從該緩衝區中獲取而不再從磁碟上獲取。
大事務binlog
mysql> show global status like 'binlog_cache%';
+-----------------------+----------+
| Variable_name | Value |
+-----------------------+----------+
| Binlog_cache_disk_use | 220840 |
| Binlog_cache_use | 67604667 |
+-----------------------+----------+
2 rows in set (0.00 sec)
- Binlog_cache_disk_use表示因為我們binlog_cache_size設計的記憶體不足導致快取二進位制日誌用到了臨時檔案的次數
- Binlog_cache_use 表示 用binlog_cache_size快取的次數
- 當對應的Binlog_cache_disk_use 值比較大的時候 我們可以考慮適當的調高 binlog_cache_size 對應的值
- 如上圖,現網是32K,我們加到64K
join語句記憶體影響
如果應用中,很少出現join語句,則可以不用太在乎join_buffer_size引數的設定大小。
如果join語句不是很少的話,個人建議可以適當增大join_buffer_size到1MB左右,如果記憶體充足可以設定為2MB。
執行緒記憶體影響
Thread_stack:每個連線執行緒被建立時,MySQL給它分配的記憶體大小。當MySQL建立一個新的連線執行緒時,需要給它分配一定大小的記憶體堆疊空間,以便存放客戶端的請求的Query及自身的各種狀態和處理資訊。
mysql> show status like '%threads%';
+-------------------------+---------+
| Variable_name | Value |
+-------------------------+---------+
| Delayed_insert_threads | 0 |
| Slow_launch_threads | 0 |
| Threadpool_idle_threads | 0 |
| Threadpool_threads | 0 |
| Threads_cached | 0 |
| Threads_connected | 1 |
| Threads_created | 9649301 |
| Threads_running | 1 |
+-------------------------+---------+
8 rows in set (0.00 sec)
mysql> show status like 'connections';
+---------------+---------+
| Variable_name | Value |
+---------------+---------+
| Connections | 9649311 |
+---------------+---------+
1 row in set (0.00 sec)
如上:系統啟動到現在共接受到客戶端的連線9649311次,共建立了9649301個連線執行緒,當前有1個連線執行緒處於和客戶端連線的狀態。而在Thread Cache池中共快取了0個連線執行緒(Threads_cached)。
Thread Cache 命中率:
Thread_Cache_Hit = (Connections - Threads_created) / Connections * 100%;
一般在系統穩定執行一段時間後,Thread Cache命中率應該保持在90%左右才算正常。
記憶體臨時表
tmp_table_size 控制記憶體臨時表的最大值,超過限值後就往硬碟寫,寫的位置由變數 tmpdir 決定
max_heap_table_size 使用者可以建立的記憶體表(memory table)的大小.這個值用來計算記憶體表的最大行數值。
Order By 或者Group By操作多的話,加大這兩個值,預設16M
mysql> show status like 'Created_tmp_%';
+-------------------------+-------+
| Variable_name | Value |
+-------------------------+-------+
| Created_tmp_disk_tables | 0 |
| Created_tmp_files | 626 |
| Created_tmp_tables | 3 |
+-------------------------+-------+
3 rows in set (0.00 sec)
- 如上圖,寫入硬碟的為0,3次中間表,說明我們的預設值足夠用了
mariadb 推薦配置
- 注意這裡只推薦innodb引擎
- 記憶體配置只關注有註釋的行
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
default-storage-engine=INNODB
character-set-server=utf8
collation-server=utf8_general_ci
user=mysql
symbolic-links=0
# global settings
table_cache=65535
table_definition_cache=65535
max_allowed_packet=4M
net_buffer_length=1M
bulk_insert_buffer_size=16M
query_cache_type=0 #是否使用查詢緩衝,0關閉
query_cache_size=0 #0關閉,因為改表操作多,命中低,開啟消耗cpu
# shared
key_buffer_size=8M #保持8M MyISAM索引用
innodb_buffer_pool_size=4G #DB專用mem*50%,非DB專用mem*15%到25%
myisam_sort_buffer_size=32M
max_heap_table_size=16M #最大中間表大小
tmp_table_size=16M #中間表大小
# per-thread
sort_buffer_size=256K #加速排序快取大小
read_buffer_size=128k #為需要全表掃描的MYISAM資料表執行緒指定快取
read_rnd_buffer_size=4M #已排序的表讀取時快取,如果比較大記憶體就到6M
join_buffer_size=1M #join語句多時加大,1-2M
thread_stack=256k #執行緒空間,256K or 512K
binlog_cache_size=64K #大事務binlog
# big-tables
innodb_file_per_table = 1
skip-external-locking
max_connections=2048 #最大連線數
skip-name-resolve
# slow_query_log
slow_query_log_file = /var/log/mysql-slow.log
long_query_time = 30
group_concat_max_len=65536
# according to tuning-primer.sh
thread_cache_size = 8
thread_concurrency = 16
# set variables
concurrent_insert=2
執行時修改
使用以下命令來修改變數
set global {要改的key} = {值}; (立即生效重啟後失效)
set @@{要改的key} = {值}; (立即生效重啟後失效)
set @@global.{要改的key} = {值}; (立即生效重啟後失效)
試驗
mysql> set @@global.innodb_buffer_pool_size=4294967296;
ERROR 1238 (HY000): Variable 'innodb_buffer_pool_size' is a read only variable
mysql> set @@global.thread_stack=262144;
ERROR 1238 (HY000): Variable 'thread_stack' is a read only variable
mysql> set @@global.binlog_cache_size=65536;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@join_buffer_size=1048576;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@read_rnd_buffer_size=4194304;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@sort_buffer_size=262144;
Query OK, 0 rows affected (0.00 sec)
mysql> set @@read_buffer_size=131072;
Query OK, 0 rows affected (0.00 sec)
mysql> set global key_buffer_size=8388608;
Query OK, 0 rows affected (0.39 sec)
- 我們可以看到
innodb_buffer_pool_size
和thread_stack
報錯了,他們只能改配置檔案,在執行時是隻讀的。 以下直接複製使用
set @@global.binlog_cache_size=65536;
set @@join_buffer_size=1048576;
set @@read_rnd_buffer_size=4194304;
set @@sort_buffer_size=262144;
set @@read_buffer_size=131072;
set global key_buffer_size=8388608;
引用
mysql 優化技巧心得一(key_buffer_size設定)
此文已由騰訊雲+社群在各渠道釋出
獲取更多新鮮技術乾貨,可以關注我們騰訊雲技術社群-雲加社群官方號及知乎機構號
相關文章
- 分析並優化 Android 應用記憶體佔用優化Android記憶體
- filebeat實踐-記憶體佔用-最大記憶體佔用記憶體
- DOTNET記憶體佔用最佳化記憶體
- win10系統如何優化記憶體_win10優化記憶體佔用率怎麼操作Win10優化記憶體
- 解決Apache長時間佔用記憶體大的問題,Apache 記憶體優化方法Apache記憶體優化
- 修改oracle記憶體佔用Oracle記憶體
- 資源記憶體佔用記憶體
- 怎樣計算Bitmap的記憶體佔用和Bitmap載入優化記憶體優化
- 字串池化,減少1/3記憶體佔用字串記憶體
- Android應用記憶體優化方式Android記憶體優化
- 記憶體優化策略記憶體優化
- UIImage 記憶體優化UI記憶體優化
- PHP記憶體優化PHP記憶體優化
- 記憶體優化技巧記憶體優化
- Android效能優化篇之記憶體優化--記憶體洩漏Android優化記憶體
- node計算記憶體佔用記憶體
- 託管堆記憶體佔用記憶體
- influxdb記憶體佔用剖析UX記憶體
- 關於redis記憶體分析,記憶體優化Redis記憶體優化
- Android效能優化 - 記憶體優化Android優化記憶體
- Chrome 再次最佳化記憶體佔用問題,新增記憶體釋放開關Chrome記憶體
- Android應用優化之記憶體概念Android優化記憶體
- 記憶體優化相關記憶體優化
- Android記憶體優化Android記憶體優化
- Python 記憶體優化Python記憶體優化
- Android 記憶體優化Android記憶體優化
- app 的記憶體優化APP記憶體優化
- 1.記憶體優化(一)記憶體洩漏記憶體優化
- Android記憶體優化之記憶體快取Android記憶體優化快取
- 實踐App記憶體優化:如何有序地做記憶體分析與優化APP記憶體優化
- python物件的記憶體佔用Python物件記憶體
- MySQL記憶體佔用計算公式MySql記憶體公式
- PHP計算出記憶體最高佔用.PHP記憶體
- Android 效能優化之記憶體優化Android優化記憶體
- Android學習之 記憶體管理機制與應用記憶體優化Android記憶體優化
- Android記憶體優化(一):Java記憶體區域Android記憶體優化Java
- Android 效能優化之記憶體洩漏檢測以及記憶體優化(上)Android優化記憶體
- Android 效能優化之記憶體洩漏檢測以及記憶體優化(下)Android優化記憶體