innodb_use_sys_malloc 配置为 ON 时,innodb_additional_mem_pool_size 失效(直接从操作系统分配内存)。

innodb_additional_mem_pool_size 和 innodb_use_sys_malloc 在 MySQL 5.7.4 中移除。

从源码中可以看出,innodb_additional_mem_pool_size 的参数值用于指定内存池 mem_comm_pool 的大小;

  1. block = static_cast<mem_block_t*>(
  2. mem_area_alloc(&len, mem_comm_pool));

如果 innodb_use_sys_malloc (上述代码中的srv_use_sys_malloc) 设置为 ON,或者内存池中没有足够的内存可供分配,则直接从操作系统中分配内存。

mem_area_alloc 调用栈如下(use database 触发断点)

  1. #0 mem_area_alloc
  2. #1 0x000000000118048d in mem_heap_create_block_func
  3. #2 0x000000000149a390 in mem_heap_create_func
  4. #3 0x00000000014aa6d5 in dict_load_table
  5. #4 0x0000000001481082 in dict_table_open_on_name
  6. #5 0x000000000109d769 in ha_innobase::open
  7. #8 0x000000000091deee in open_table
  8. #9 0x0000000000922eea in open_and_process_table
  9. #10 0x000000000092492f in open_tables
  10. #11 0x0000000000926c21 in open_normal_and_derived_tables
  11. #12 0x0000000000a83834 in mysqld_list_fields
  12. #13 0x00000000009f28e1 in dispatch_command
  13. #14 0x00000000009eeb51 in do_command
  14. #15 0x0000000000982cb6 in do_handle_one_connection
  15. #16 0x000000000098238b in handle_one_connection
  16. #17 0x0000000001877f91 in pfs_spawn_thread

函数 dict_load_table 中会为每张表分配32k的空间 ( mem_heap_create(32000) 实际分配32744字节空间 ),数据字典中每张表所占空间的上限是32k,具体占用空间根据列数和索引数量分配,分配完成后回收32k中未使用的空间

实际使用的数据字典缓存,不会超过每张表32k,实测过程中,每张表不包括索引占4K,每个索引占2k,列数对空间占用影响不大。

测试用表如下,未建索引时,1000张表占用空间4M,增加列占用空间增长不明显,每增加一个索引,占用空间增加2M,可以估测每张表占用空间4k(不含索引),每个索引占用空间2k。

  1. Create Table: CREATE TABLE `1000` (
  2. `id` int(11) DEFAULT NULL,
  3. `a` varchar(255) DEFAULT NULL,
  4. `b` varchar(255) DEFAULT NULL,
  5. `c` varchar(255) DEFAULT NULL,
  6. `d` varchar(255) DEFAULT NULL,
  7. KEY `a` (`a`),
  8. KEY `b` (`b`),
  9. KEY `id` (`id`)

早期操作系统的内存分配器性能和可伸缩性较差,并且当时没有适合多核心CPU的内存分配器。所以,InnoDB 实现了一套自己的内存分配系统,做为内存系统的参数之一,引入了innodb_additional_mem_pool_size