本文由雲+社區發表mysql
做者:工程師小熊sql
摘要:咱們在使用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計算器來計算內存使用數據結構
下面是理論,能夠直接到推薦配置併發
指定索引緩衝區的大小,它決定索引處理的速度,尤爲是索引讀的速度。爲了最小化磁盤的 I/O , MyISAM 存儲引擎的表使用鍵高速緩存來緩存索引,這個鍵高速緩存的大小則經過 key-buffer-size 參數來設置。若是應用系統中使用的表以 MyISAM 存儲引擎爲主,則應該適當增長該參數的值,以便儘量的緩存索引,提升訪問的速度。oracle
show global status like 'key_read%';
+------------------------+-------------+
| Variable_name | Value |
+------------------------+-------------+
| Key_read_requests | 27813678764 |
| Key_reads | 6798830 |
---------------------
複製代碼
show global status like '%created_tmp_disk_tables%';
複製代碼
另外一個參考以下socket
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;
複製代碼
這個參數和MyISAM的
key_buffer_size
有類似之處,但也是有差異的。這個參數主要緩存innodb表的索引,數據,插入數據時的緩衝。爲Innodb加速優化首要參數。 學習
該參數分配內存的原則:這個參數默認分配只有8M,能夠說是很是小的一個值。
緩存機制簡單的說就是緩存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數量。
InnoDB 字典信息緩存主要用來存放 InnoDB 存儲引擎的字典信息以及一些 internal 的共享數據結構信息,也就是存放Innodb的內部目錄,因此其大小也與系統中所使用的 InnoDB 存儲引擎表的數量有較大關係。
這個值不用分配太大,一般設置16M夠用了,默認8M,若是設置的內存大小不夠,InnoDB 會自動申請更多的內存,並在 MySQL 的 Error Log 中記錄警告信息。
表示InnoDB寫入到磁盤上的日誌文件時使用的緩衝區的字節數,默認值爲16M。一個大的日誌緩衝區容許大量的事務在提交以前不用寫日誌到磁盤,因此若是有更新,插入或刪除許多行的事務,則使日誌緩衝區更大一些能夠節省磁盤IO
一般最大設爲64M足夠
MySQL的max_connections參數用來設置最大鏈接(用戶)數。每一個鏈接MySQL的用戶均算做一個鏈接,max_connections的默認值爲100。
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第一次須要使用這個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)首先,該變量能夠被任何存儲引擎使用,當從一個已經排序的鍵值表中讀取行時,會先從該緩衝區中獲取而再也不從磁盤上獲取。
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)
複製代碼
若是應用中,不多出現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)
複製代碼
[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設置)
此文已由騰訊雲+社區在各渠道發佈
獲取更多新鮮技術乾貨,能夠關注咱們騰訊雲技術社區-雲加社區官方號及知乎機構號