搜索
您的当前位置:首页正文

MySQL内存相关参数设置

2023-10-26 来源:欧得旅游网
MySQL内存相关参数设置

read_buffer_size = 16M

MyISAM 表顺序扫描的缓存⼤⼩,如果要经常顺序扫描 MyISAM 表,可以通过增⼤ read_buffer_size 的值来改善性能,但是这个变量是每会话独占,如果设置太⼤,会造成内存浪费,甚⾄物理内存耗尽。

在以下场景中适⽤于所有的存储引擎

此选项也在以下场景中⽤于所有存储引擎:

* 控制 ORDER BY ⾏排序时的临时⽂件(不是临时表,⽽是排序的⽂件)中缓存索引的⼤⼩* 控制批量插⼊到分区中的数据⼤⼩* 控制缓存嵌套查询的结果集⼤⼩

memory 存储引擎中该参数的值决定 MEMORY 表的内存块⼤⼩,注意是块⼤⼩,⽽不是 memory 表可以使⽤的内存总⼤⼩,memory 引擎表的数据总⼤⼩限由max_heap_table_size 参数控制。

全局,会话变量,默认为 128K,最⼤为 2G,整型值。注意:设置值必须为 4K 的倍数,否则会截取你设定值的最接近 4K 的倍数的值作为该参数的值。取值范围为:8200~2147479552 字节。

PS:为啥这个变量官⽅描述的是⽤于 MyISAM,⽽在某些场景也适⽤于所有存储引擎呢?因为在这些场景下,mysql 内部保存这些临时数据仍然使⽤的是MyISAM 表,在 mysql 5.7.x 的版本中,这些内部临时表可以设置使⽤ InnoDB 存储引擎,如果临时表设置为 InnoDB 存储引擎,则这个参数的⼤⼩就⽆需多关注了(除⾮你使⽤ MyISAM 引擎和 memory 引擎)。

read_rnd_buffer_size = 32M

MyISAM 表排序缓存的缓存⼤⼩(注意,是 key-sorting 索引排序),如果需要对 MyISAM 表做排序,可以增⼤ read_rnd_buffer_size 改善性能,这个变量同样的每会话独占,也不能设置太⼤。

该变量控制的 buffer 在从任何存储引擎读取数据的时候,都会⽤于缓存读取的数据,包括 MRR 优化特性也会使⽤。全局,会话变量,动态变量,默认值为 256K,最⼤值为 2G,整型值。取值范围 1~2147483647 字节(2G)。

sort_buffer_size = 32M

⽤于存放排序数据的缓存⼤⼩,超过这个⼤⼩就会使⽤⽂件排序。如果通过 show global status 看到 Sort_merge_passes 的值很⼤,可以考虑通过适当调整

sort_buffer_size 的值来增⼤排序缓存区(另外增加max_sort_length 参数的值时可能也需要增加 sort_buffer_size 参数的值),改善带有 order by 和 group by ⼦句的sql 性能。sort_buffer_size 是每线程独占分配(每个执⾏排序操作的会话才会分配),不要设置过⼤,最好是设置⼀个较⼩的全局值,如果碰到较⼤表做排序,就对这个 session 设置较⼤的值。

该参数适通⽤于所有存储引擎,最⼩值必须要⾜够⼤,⾄少要在排序缓冲中能够存放 15 个排序元组。

5.6.4 之前的版本总是在有排序操作时直接分配整个排序缓冲给会话,从 5.6.4 版本开始优化器尝试计算排序数据的⼤⼩来分配排序缓冲的⼤⼩给会话。在 linux 上,⼤于 256K 或者 2M 的排序缓冲⼤⼩可能显著降低内存分配的性能。

全局变量,会话变量,动态变量,默认值在不同版本中频繁变化,⼤于 5.6.4 版本号的 64 位版本默认值为 256K,整型值。64位平台取值范围为:32768~18446744073709551615 字节。

tmp_table_size = 64M

内存临时表超过这个⼤⼩后,就会把内存临时表转换为磁盘临时表,线程级别的参数,不要设置过⼤,⼀般全局设置不⼤于 100M 就可以了,否则很容易发⽣内存溢出,但是,如果说在临时⼤数据查询的时候,可以打开⼀个会话临时设置⼤⼀点,避免产⽣临时磁盘表。或者,可以使⽤索引查询尽量减少返回的数据量。

内部⽤于控制内存临时表⼤⼩使⽤,是适⽤于⽤户创建的内存表和临时表。

实际限制从 tmp_table_size 和 max_heap_table_size 两个变量的的值中取较⼩值。 如果内存中临时表超过这个限制,MySQL会⾃动将其转换为磁盘上的MyISAM 表。 如果您执⾏许多⾼级GROUP BY 查询并且⽤到⼤量内存,请增加 tmp_table_size 的值(如果必要,也请增加 max_heap_table_size 的值)。状态变量 Created_tmp_disk_tables 持续增加时,需要增加tmp_table_size 的值。

Created_tmp_disk_tables/(Created_tmp_disk_tables+Created_tmp_tables)*100% > 10%的话,就需要注意适当提⾼tmp_table_size 的⼤⼩,但是不能设置太⼤,因为它是每个session 都会分配的,可能会导致 OOM(out of memory)。

全局变量,会话变量,动态变量,默认值为 16M,整型值。取值范围为:1024~18446744073709551615 字节。

max_heap_table_size=64M

默认是 16M,可以根据需要加⼤,在定义内存表时,可以使⽤max_rows ⼦句指定表的最⼤⾏数来约定内存表的数据量。该参数是⽤于控制⽤户创建的内存表的数据⼤⼩。

设置此变量不会影响任何现有的 MEMORY 表,除⾮使⽤如CREATE TABLE 或使⽤ ALTER TABLE 或 TRUNCATE TABLE 语句重新创建表、修改表结构或清空表数据。 服务器重新启动也会将现有 MEMORY 表的数据最⼤⼤⼩限制设置为全局max_heap_table_size 值。

此变量也与 tmp_table_size 结合使⽤以限制内部内存表的⼤⼩。如果设置与 tmp_table_size ⼤⼩不⼀样,则控制内部内存临时表以较⼩的为准。全局变量,会话变量,动态变量,64 位版本默认值为 16M,整型值。取值范围为:16384~1844674407370954752 字节。

join_buffer_size = 32M

⽤于存放 join 查询中间结果的缓存⼤⼩。对于⽆法通过索引进⾏联结操作的查询,可以通过适当增⼤ join_buffer_size 的值来改善联结查询性能(但最好是想办法让join 使⽤到索引来提⾼性能)。join_buffer_size 都是每线程独占分配,不要设置过⼤(除⾮能够使⽤BKA 特性,当使⽤ BKA 时,join_buffer_size 的值的⼤⼩决定了向存储引擎的每个请求中包含的键值对的多少,缓冲区越⼤,联结操作的右表即被驱动表的顺序 I/O 访问就越多,BKA 的作⽤就是把随机 I/O 访问变为顺序 I/O 访问,这可以显着提⾼性能),最好是设置⼀个较⼩的全局值,如果碰到较⼤表做联结查询,或者是⽐较复杂的联结表查询,就对这个 session 设置较⼤的值。

对于简单查询的索引扫描、索引范围扫描以及因为不能使⽤到索引做全表扫描的 join 查询时,⽆论返回的数据多⼤,都会分配该参数的最⼩值 128 字节那么多join buffer 做查询。

对于简单的两个表之间的查询分配⼀个 join buffer,但是对于复杂的多表 join 查询且不能使⽤索引的时候,可能会分配多个 join buffer。

全局变量,会话变量,动态变量,默认值在不同版本中频繁变化,⼤于 5.6.6 版本号的 64 位版本默认值为 256K,最⼩值为128 字节,整型值。取值范围为:128~18446744073709547520 字节。

thread_cache_size = 64

为加快数据库连接的速度,mysql 会缓存⼀定数量的客户端服务线程以备重⽤,通过这个参数可以控制 mysql 缓存客户端服务线程的数量,可以通过计算线程 cache的失效率:Threads_created/Connections 状态变量⽐值来衡量 thread_cache_size 参数的设置是否合理,该值越接近 1,说明线程 cache 的命中率越低,就应该考虑增加这个参数的值。

当⼀个客户端访问完成断开连接时,如果线程缓存中的客户端连接线程没有达到 thread_cache_size 定义的值,则这个客户端线程会被 put 到缓存中,当另外⼀个客户端新建连接时,如果线程缓存不为空(即有客户端线程缓存在线程缓存中),就会从缓存中取出这个客户端连接进⾏重⽤。在⼤多数情况下,如果你的并发连接不⾼的时候,这个值对性能的影响可能就看不出来,但是当有⼤量并发连接时,通过增⼤这个值可以缓解⾼并发连接的压⼒。默认值为-1,表⽰⾃动计算(计算公式:8 + (max_connections/ 100)),全局变量,动态变量,整型值。固定值取值范围为:0~16384PS:这个变量对嵌⼊式服务器(libmysqld)没有任何影响,⽽在 MySQL 5.7.2 在嵌⼊式服务器中移除了这个变量。

参数:

⼀、线程独享内存

在MySQL中,线程独享内存主要⽤于各客户端连接线程存储各种操作的独享数据,如线程栈信息,分组排序操作,数据读写缓冲,结果集暂存等等,⽽且⼤多数可以通过相关参数来控制内存的使⽤量。

* 线程栈信息使⽤内存(thread_stack):

主要⽤来存放每⼀个线程⾃⾝的标识信息,如线程id,线程运⾏时基本信息等等,我们可以通过 thread_stack 参数来设置为每⼀个线程栈分配多⼤的内存。Global,No Dynamic,Default 192K(32bit), 256K(32bit),推荐配置:默认

* 排序使⽤内存(sort_buffer_size):

MySQL ⽤此内存区域进⾏排序操作(filesort),完成客户端的排序请求。当我们设置的排序区缓存⼤⼩⽆法满⾜排序实际所需内存的时候,MySQL会将数据写⼊磁盘⽂件来完成排序。由于磁盘和内存的读写性能完全不在⼀个数量级,

所以sort_buffer_size参数对排序操作的性能影响绝对不可⼩视。排序操作的实现原理请参考:MySQL Order By的实现分析。什么时候会⽤到?对结果集排序时

使⽤确认:

可以通过查询计划中的Extra列的值为Using file-sort来证实使⽤了和这个缓冲区。>explain select * from user1;

Global Session,Dynamic,Default 2M(32bit), 2M(32bit),

推荐配置:8M(内存⾜够的情况下),默认(内存紧张的情况)

优化建议:⼀种说法是增⼤可以提⾼order by,group by性能,防⽌数据写⼊磁盘占⽤IO资源,还有⼀种说法是不推荐增加这个缓冲区的⼤⼩,理由是当值太⼤时可能会降低查询的执⾏速度。⽬前我没有实验证实。

* Join操作使⽤内存(join_buffer_size):

应⽤程序经常会出现⼀些两表(或多表)Join的操作需求,MySQL在完成某些Join需求的时候(all/index join),为了减少参与Join的“被驱动表”的读取次数以提⾼性能,需要使⽤到Join Buffer来协助完成Join操作

(具体Join实现算法请参考:MySQL中的 Join 基本实现原理)。当Join Buffer太⼩,MySQL 不会将该Buffer存⼊磁盘⽂件,⽽是先将Join Buffer中的结果集与需要Join的表进⾏Join操作,然后清空Join Buffer中的数据,

继续将剩余的结果集写⼊此Buffer中,如此往复。这势必会造成被驱动表需要被多次读取,成倍增加IO访问,降低效率。什么时候会⽤到?

当查询必须连接两个表(或多个)的数据集并且不能使⽤索引时,这个缓冲区会被⽤到。这个缓冲区专门为每个线程的⽆索引链接操作准备的。使⽤确认:

可以通过查询计划中的Extra列的值为Using join bufer来证实使⽤了和这个缓冲区。

>explain select * from user1;

+------+-------------+-------+-------+---------------+------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+------+-------------+-------+-------+---------------+------+---------+------+------+-------------+| 1 | SIMPLE | user1 | index | NULL | name | 78 | NULL | 3 | Using index |+------+-------------+-------+-------+---------------+------+---------+------+------+-------------+mysql> show global status like 'create%tables';+-------------------------+-------+| Variable_name | Value |+-------------------------+-------+

| Created_tmp_disk_tables | 0 || Created_tmp_tables | 0 |+-------------------------+-------+

5.5中,可以使⽤PERFORMANCE—SCHEMA来帮助统计基于磁盘的临时表的总⼤⼩

补充说明:上⾯所列举的MySQL线程独享内存仅仅只是所有线程独享内存中的部分,并不是全部,只是这些可能对MySQL的性能产⽣较⼤的影响,且可以通过系统参数进⾏调节。

由于以上内存都是线程独享,极端情况下的内存总体使⽤量将是所有连接线程的总倍数。所以在设置过程中⼀定要谨慎,切不可为了提升性能就盲⽬的增⼤各参数值,避免因为内存不够⽽产⽣Out Of Memory异常或者是严重的Swap交换反⽽降低整体性能。

⼆、全局共享内存

mysql> show variables like 'query_cache_size';+------------------+----------+| Variable_name | Value |+------------------+----------+

| query_cache_size | 16777216 |+------------------+----------+1 row in set (0.00 sec)

mysql> show global status like 'Qcache%';+-------------------------+------------+| Variable_name | Value |

+-------------------------+------------+| Qcache_free_blocks | 535 |

| Qcache_free_memory | 4885448 || Qcache_hits | 1858574835 || Qcache_inserts | 1619931831 |

| Qcache_lowmem_prunes | 802889469 || Qcache_not_cached | 825000679 || Qcache_queries_in_cache | 4411 || Qcache_total_blocks | 9554 |+-------------------------+------------+8 rows in set (0.00 sec)

mysql> show global status like 'Com_select';+---------------+------------+| Variable_name | Value |+---------------+------------+

| Com_select | 2445037535 |+---------------+------------+1 row in set (0.00 sec)

* 连接线程缓存 Thread Cache(thread_cache_size):

连接线程是MySQL为了提⾼创建连接线程的效率,将部分空闲的连接线程保持在⼀个缓存区以备新进连接请求的时候使⽤,这尤其对那些使⽤短连接的应⽤程序来说可以极⼤的提⾼创建连接的效率。

当我们通过thread_cache_size设置了连接线程缓存池可以缓存的连接线程的⼤⼩之后,可以通过(Connections - Threads_created) / Connections * 100% 计算出连接线程缓存的命中率。

注意,这⾥设置的是可以缓存的连接线程的数⽬,⽽不是内存空间的⼤⼩。Global,Dynamic,Default 0推荐配置:8个

如何确定系统Thread Cache的情况?

mysql> show global status like 'Threads_created';+-----------------+-------+| Variable_name | Value |+-----------------+-------+| Threads_created | 506 |+-----------------+-------+1 row in set (0.00 sec)

mysql> show global status like 'connections';+---------------+----------+| Variable_name | Value |+---------------+----------+

| Connections | 16513711 |+---------------+----------+1 row in set (0.00 sec)

16513711-506/16513711 * 100% =99.9938% 很⾼的命中率啊 这台之只读的slave

* 表缓存 Table Cache(table_open_cache):

表缓存区主要⽤来缓存表⽂件的⽂件句柄信息,在 MySQL5.1.3之前的版本通过table_cache参数设置,但从MySQL5.1.3开始改为table_open_cache来设置其⼤⼩。当我们的客户端程序提交Query给MySQL的时候,

MySQL需要对Query所涉及到的每⼀个表都取得⼀个表⽂件句柄信息,如果没有Table Cache,那么MySQL就不得不频繁的进⾏打开关闭⽂件操作,⽆疑会对系统性能产⽣⼀定的影响,Table Cache 正是为了解决这⼀问题⽽产⽣的。

在有了Table Cache之后,MySQL每次需要获取某个表⽂件的句柄信息的时候,⾸先会到Table Cache中查找是否存在空闲状态的表⽂件句柄。如果有,则取出直接使⽤,没有的话就只能进⾏打开⽂件操作获得⽂件句柄信息。

在使⽤完之后,MySQL会将该⽂件句柄信息再放回Table Cache 池中,以供其他线程使⽤。注意,这⾥设置的是可以缓存的表⽂件句柄信息的数⽬,⽽不是内存空间的⼤⼩。Global,Dynamic,Default 400

推荐配置:根据内存配置4G 2048 ⼤于最⼤Opened_tables如何确定系统table_open_cache的情况?

mysql> show variables like 'table_open_cache';+------------------+-------+| Variable_name | Value |+------------------+-------+

| table_open_cache | 512 |+------------------+-------+1 row in set (0.00 sec)

mysql> show global status like 'open%_tables';+---------------+-------+

| Variable_name | Value |+---------------+-------+| Open_tables | 512 || Opened_tables | 6841 |+---------------+-------+2 rows in set (0.00 sec)

调优参考:

mysql> show variables like '%innodb_buffer%';+------------------------------+-----------+| Variable_name | Value |

+------------------------------+-----------+| innodb_buffer_pool_instances | 1 || innodb_buffer_pool_size | 268435456 |+------------------------------+-----------+2 rows in set (0.00 sec)

通过show global status和show engine innodb status/G的BUFFER POOL AND MEMORY

mysql> show global status like '%innodb_buffer%';+---------------------------------------+--------------+| Variable_name | Value |

+---------------------------------------+--------------+| Innodb_buffer_pool_pages_data | 15684 || Innodb_buffer_pool_bytes_data | 256966656 || Innodb_buffer_pool_pages_dirty | 210 || Innodb_buffer_pool_bytes_dirty | 3440640 |

| Innodb_buffer_pool_pages_flushed | 372378403 || Innodb_buffer_pool_pages_free | 1 || Innodb_buffer_pool_pages_misc | 698 || Innodb_buffer_pool_pages_total | 16383 || Innodb_buffer_pool_read_ahead_rnd | 0 || Innodb_buffer_pool_read_ahead | 691803 |

| Innodb_buffer_pool_read_ahead_evicted | 41350 || Innodb_buffer_pool_read_requests | 170965099291 || Innodb_buffer_pool_reads | 5392513 || Innodb_buffer_pool_wait_free | 0 |

| Innodb_buffer_pool_write_requests | 5825388207 |+---------------------------------------+--------------+15 rows in set (0.01 sec)

mysql> show engine innodb status/GBUFFER POOL AND MEMORY----------------------Total memory allocated 274726912; in additional pool allocated 0Dictionary memory allocated 4055091Buffer pool size 16383Free buffers 1

Database pages 15673Old database pages 5765Modified db pages 521Pending reads 0

Pending writes: LRU 0, flush list 0, single page 0Pages made young 27497746, not young 00.00 youngs/s, 0.00 non-youngs/s

Pages read 6346456, created 1902566, written 3723817120.00 reads/s, 0.37 creates/s, 27.75 writes/s

Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000

Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/sLRU len: 15673, unzip_LRU len: 0

I/O sum[1107]:cur[0], unzip sum[0]:cur[0]

命中率 Innodb_buffer_pool_read_requests - Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100%170965099291-5392513/170965099291 × 100% = 99.99%

* InnoDB 字典信息缓存 InnoDB Additional Memory Pool(innodb_additional_mem_pool_size):

InnoDB 字典信息缓存主要⽤来存放 InnoDB 存储引擎的字典信息以及⼀些 internal 的共享数据结构信息。所以其⼤⼩也与系统中所使⽤的 InnoDB 存储引擎表的数量有较⼤关系。不过,如果我们通过 innodb_additional_mem_pool_size 参数所设置的内存⼤⼩不够,InnoDB 会⾃动申请更多的内存,并在 MySQL 的 Error Log 中记录警告信息。global级别,不可动态变更 Default 8M

设置InnoDB存放数据库字典信息的Buffer⼤⼩推荐配置:50M

三、查看统计

1.查看各参数内存配置⽅式#全局共享内存 9个变量

show variables like 'innodb_buffer_pool_size'; /* InnoDB 数据和索引缓存(InnoDB Buffer Pool) */

show variables like 'innodb_additional_mem_pool_size'; /* InnoDB 字典信息缓存(InnoDB Additional Memory Pool)*/show variables like 'innodb_log_buffer_size'; /* InnoDB ⽇志缓冲区(InnoDB Log Buffer) */show variables like 'binlog_cache_size'; /* ⼆进制⽇志缓冲区(Binlog Buffer)*/show variables like 'thread_cache_size'; /* 连接线程缓存(Thread Cache)*/show variables like 'query_cache_size'; /* 查询缓存(Query Cache)*/show variables like 'table_open_cache'; /* 表缓存(Table Cache) */

show variables like 'table_definition_cache'; /* 表定义信息缓存(Table definition Cache) */show variables like 'key_buffer_size'; /* MyISAM索引缓存(Key Buffer) */#最⼤线程数

show variables like 'max_connections';#线程独享内存 6个变量

show variables like 'thread_stack'; /* 线线程栈信息使⽤内存(thread_stack) */show variables like 'sort_buffer_size'; /* 排序使⽤内存(sort_buffer_size) */

show variables like 'join_buffer_size'; /* Join操作使⽤内存(join_buffer_size) */

show variables like 'read_buffer_size'; /* 顺序读取数据缓冲区使⽤内存(read_buffer_size) */

show variables like 'read_rnd_buffer_size'; /* 随机读取数据缓冲区使⽤内存(read_rnd_buffer_size) */

show variables like 'tmp_table_size'; /* 临时表使⽤内存(tmp_table_size) ,我实际计算把tmp_table_size放⼊全局共享内*/也可以通过系统变量的⽅式直接获取select @@key_buffer_size;select @@max_connections

2.mysql内存计算公式

mysql使⽤的内存 = 全局共享内存+最⼤线程数×线程独享内存

mysql used mem=innodb_buffer_pool_size+innodb_additional_mem_pool_size+innodb_log_buffer_size+binlog_cache_size+thread_cache_size+query_cache_size+table_open_cache+table_definition_cache+key_buffer_size+max_connections*(

thread_stack+sort_buffer_size+join_buffer_size+read_buffer_size+read_rnd_buffer_size+tmp_table_size)

SET @kilo_bytes=1024;

SET @mega_bytes=@kilo_bytes*1024;SET @giga_bytes=@mega_bytes*1024;

SELECT (@@innodb_buffer_pool_size+@@innodb_additional_mem_pool_size+@@innodb_log_buffer_size+@@binlog_cache_size+@@thread_cache_size+@@query_cache_size+@@table_open_cache+@@table_definition_cac

这个理论最⼤的内存使⽤量,在5.5版本中tmp_table_size默认是16M,按默认u⾃⼤连接数151计算,光线程独享的临时表占据的空间都是2416M,我实际计算把tmp_table_size放⼊全局共享内我的计算公式

mysql使⽤的内存 = 全局共享内存+最⼤线程数×线程独享内存

mysql used mem=innodb_buffer_pool_size+innodb_additional_mem_pool_size+innodb_log_buffer_size+binlog_cache_size+thread_cache_size+query_cache_size+table_open_cache+table_definition_cache+key_buffer_size+tmp_table_size+max_connections*(

thread_stack+sort_buffer_size+join_buffer_size+read_buffer_size+read_rnd_buffer_size)

因篇幅问题不能全部显示,请点此查看更多更全内容

Top