1. 程式人生 > >MySQL將內存用在了哪裏

MySQL將內存用在了哪裏

fin enabled 在線 for gin ash 啟動 行數 AC

本片文章參考官網講述MySQL是如何分配內部內存,同時涉及到如何合適設的置內存分配以及如何監控內存的使用情況

官方文檔

MySQL在啟動時默認被分配給512MB RAM,可以通過設置相關內存參數對其進行設置,下面時MySQL使用內存的地方

1、InnoDB buffer pool 用於緩存表數據、索引及其他的一些輔助緩沖池,為了高效進行緩存管理,buffer pool 應用多種LRU(least recently used)算法,將相鄰的page串成鏈,管理冷熱數據

  • innodb_buffer_pool_size控制buffer pool的大小,MySQL5.7開始,可以在線變更配置
  • 為了提高並行,可以將buffer pool分成多個實例,默認如果buffer pool的大小達到1GB,instance的個數時8,可以通過innodb_buffer_pool_instances配置

2、所有的線程共享MyISAM key buffer ,受key_buffer_size參數控制

每打開一個MyISAM表,索引文件只會打開一次,當多個線程並行打開同一個表時,此表只會被打開一次,但是單個線程內,表結構、列結構及3*N(N是最長行的大小,不包括blob列)的緩存都會被分配內存。BLOB列需要5到8個bytes加上BLOB數據。MyISAM存儲引擎額外分配一個row buffer 用於內部

3、內部的內存臨時表如果超過設置大小則轉為磁盤表,控制內存臨時表的大小參數有tmp_table_size、max_heap_table_size,on-disk臨時表的存儲引擎受internal_tmp_disk_storage_engine設置

4、performance schema根據服務器的實際負載自增分配內存,已分配的內存只有在MySQL重啟時才會釋放

5、為每個客戶端線程分配線程所需的內存,包括

  • A stack (thread_stack)

  • A connection buffer (net_buffer_length)

  • A result buffer (net_buffer_length)

connection buffer 和result buffer 最初的大小是 net_buffer_length bytes, 但是根據需要可以動態的擴大到 max_allowed_packet bytes 。 result buffer 收縮到 net_buffer_length

bytes 當執行每個sql 後. 當語句正在執行中,當前statement的文本的副本也會被緩存。每個連接線程使用內存計算語句的摘要,服務器為每個會話分配max_digest_length bytes

6、所有線程共享共同的基礎系統內存

7、當線程不再被使用時,為其分配的內存將被回收並重新歸為系統,除非使用長連接,線程回到緩沖池,對其分配的內存不會釋放

8、順序讀表被分配一個read buffer ,受read_buffer_size控制

9、隨機讀取行數據會被分配random-read buffer ,受read_rnd_buffer_size控制

10、所有連接都在一次執行中執行,大多數連接都可以在不使用臨時表的情況下完成。

11、大多數的排序會占用一個sort buffer和0到2個臨時文件(根據結果集的大小而定)

12、幾乎所有的解析和計算都是在線程本地和可重用的內存池中完成的。

13、對於每個含有BLOB列的表,會占用一個自動擴大的buffer用於讀入更大的BLOB值,如果進行全表掃描,這個buffer會擴大到和最大的BLOB值一樣大

14、MySQL的table cache需要內存和描述符,所有使用中的表結構的處理程序都緩存在table cache中,管理原則時先進先出(FIFO),table cache受table_open_cache控制

MySQL同樣需要內存緩存表結構文件,受table_definition_cache控制,不需要描述符,可以增大table definition cache來加快表的打開速度

15、flush tables 命令會關閉所有不使用的表並標記當前正在使用的表在調用他們的線程結束後被關閉。會有效的釋放內存,flush tables在表都關閉後才會返回

16、MySQL會緩存權限、server、插件相關的命令文本,只有執行flush privileges後才會釋放內存

監控MySQL的使用情況

查看innodb相關的內存監控是否開啟,默認不開啟

mysql> SELECT * FROM performance_schema.setup_instruments
       WHERE NAME LIKE %memory/innodb%;
+-------------------------------------------+---------+-------+
| NAME                                      | ENABLED | TIMED |
+-------------------------------------------+---------+-------+
| memory/innodb/adaptive hash index         | NO      | NO    |
| memory/innodb/buf_buf_pool                | NO      | NO    |
| memory/innodb/dict_stats_bg_recalc_pool_t | NO      | NO    |
| memory/innodb/dict_stats_index_map_t      | NO      | NO    |
| memory/innodb/dict_stats_n_diff_on_level  | NO      | NO    |
| memory/innodb/other                       | NO      | NO    |
| memory/innodb/row_log_buf                 | NO      | NO    |
| memory/innodb/row_merge_sort              | NO      | NO    |
| memory/innodb/std                         | NO      | NO    |
| memory/innodb/trx_sys_t::rw_trx_ids       | NO      | NO    |
...

設置開啟所有的memory instruments ,配置文件條件如下並重啟

performance-schema-instrument=memory/%=COUNTED

查看監控數據

mysql> SELECT * FROM performance_schema.memory_summary_global_by_event_name
       WHERE EVENT_NAME LIKE memory/innodb/buf_buf_pool\G
                  EVENT_NAME: memory/innodb/buf_buf_pool
                 COUNT_ALLOC: 1
                  COUNT_FREE: 0
   SUM_NUMBER_OF_BYTES_ALLOC: 137428992
    SUM_NUMBER_OF_BYTES_FREE: 0
              LOW_COUNT_USED: 0
          CURRENT_COUNT_USED: 1
             HIGH_COUNT_USED: 1
    LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 137428992
   HIGH_NUMBER_OF_BYTES_USED: 137428992

通過sys庫查看當前server分配的所有內存

mysql> SELECT * FROM sys.memory_global_by_current_bytes
       WHERE event_name LIKE memory/innodb/buf_buf_pool\G
*************************** 1. row ***************************
       event_name: memory/innodb/buf_buf_pool
    current_count: 1
    current_alloc: 131.06 MiB
current_avg_alloc: 131.06 MiB
       high_count: 1
       high_alloc: 131.06 MiB
   high_avg_alloc: 131.06 MiB
# 細化查詢每個code area 分配的內存
mysql> SELECT SUBSTRING_INDEX(event_name,/,2) AS
       code_area, sys.format_bytes(SUM(current_alloc))
       AS current_alloc
       FROM sys.x$memory_global_by_current_bytes
       GROUP BY SUBSTRING_INDEX(event_name,/,2)
       ORDER BY SUM(current_alloc) DESC;
+---------------------------+---------------+
| code_area                 | current_alloc |
+---------------------------+---------------+
| memory/innodb             | 843.24 MiB    |
| memory/performance_schema | 81.29 MiB     |
| memory/mysys              | 8.20 MiB      |
| memory/sql                | 2.47 MiB      |
| memory/memory             | 174.01 KiB    |
| memory/myisam             | 46.53 KiB     |
| memory/blackhole          | 512 bytes     |
| memory/federated          | 512 bytes     |
| memory/csv                | 512 bytes     |
| memory/vio                | 496 bytes     |
+---------------------------+---------------+

MySQL將內存用在了哪裏