MySQL内存使用
对于任何一个数据库管理系统来说,内存的分配使用绝对可以算的上是其核心之一了,所以很多希望更为深入了解某数据库管理系统的人,都会希望一窥究竟,我也不例外。
从内存的使用方式MySQL 数据库的内存使用主要分为以下两类
线程独享内存
在 MySQL 中,线程独享内存主要用于各客户端连接线程存储各种操作的独享数据,如线程栈信息,分组排序操作,数据读写缓冲,结果集暂存等等,而且大多数可以通过相关参数来控制内存的使用量。
线程栈信息使用内存(thread_stack)
:主要用来存放每一个线程自身的标识信息,如线程id,线程运行时基本信息等等,我们可以通过 thread_stack 参数来设置为每一个线程栈分配多大的内存。
排序使用内存(sort_buffer_size)
:MySQL
用此内存区域进行排序操作(filesort),完成客户端的排序请求。当我们设置的排序区缓存大小无法满足排序实际所需内存的时候,MySQL会将数据
写入磁盘文件来完成排序。由于磁盘和内存的读写性能完全不在一个数量级,所以sort_buffer_size参数对排序操作的性能影响绝对不可小视。
Join操作使用内存(join_buffer_size)
:
应用程序经常会出现一些两表(或多表)Join的操作需求,MySQL在完成某些 Join
需求的时候(all/indexjoin),为了减少参与Join的“被驱动表”的读取次数以提高性能,需要使用到 Join Buffer 来协助完成
Join操作。当 Join Buffer 太小,MySQL 不会将该 Buffer 存入磁盘文件,而是先将Join
Buffer中的结果集与需要 Join的表进行 Join 操作,然后清空 Join Buffer 中的数据,继续将剩余的结果集写入此
Buffer中,如此往复。这势必会造成被驱动表需要被多次读取,成倍增加 IO 访问,降低效率。
顺序读取数据缓冲区使用内存(read_buffer_size)
:
这部分内存主要用于当需要顺序读取数据的时候,如无发使用索引的情况下的全表扫描,全索引扫描等。在这种时候,MySQL按照数据的存储顺序依次读取数据
块,每次读取的数据快首先会暂存在read_buffer_size中,当
buffer空间被写满或者全部数据读取结束后,再将buffer中的数据返回给上层调用者,以提高效率。
随机读取数据缓冲区使用内存(read_rnd_buffer_size)
:
和顺序读取相对应,当MySQL进行非顺序读取(随机读取)数据块的时候,会利用这个缓冲区暂存读取的数据。如根据索引信息读取表数据,根据排序后的结果
集与表进行Join等等。总的来说,就是当数据块的读取需要满足一定的顺序的情况下,MySQL 就需要产生随机读取,进而使用到
read_rnd_buffer_size参数所设置的内存缓冲区。
连接信息及返回客户端前结果集暂存使用内存(net_buffer_size)
:
这部分用来存放客户端连接线程的连接信息和返回客户端的结果集。当 MySQL
开始产生可以返回的结果集,会在通过网络返回给客户端请求线程之前,会先暂存在通过net_buffer_size所设置的缓冲区中,等满足一定大小的时
候才开始向客户端发送,以提高网络传输效率。不过,net_buffer_size参数所设置的仅仅只是该缓存区的初始化大小,MySQL
会根据实际需要自行申请更多的内存以满足需求,但最大不会超过max_allowed_packet 参数大小。
批量插入暂存使用内存(bulk_insert_buffer_size):
当
我们使用如 insert …values(…),(…),(…)…
的方式进行批量插入的时候,MySQL会先将提交的数据放如一个缓存空间中,当该缓存空间被写满或者提交完所有数据之后,MySQL才会一次性将该缓存空
间中的数据写入数据库并清空缓存。此外,当我们进行 LOAD DATA INFILE 操作来将文本文件中的数据
Load进数据库的时候,同样会使用到此缓冲区。
临时表使用内存(tmp_table_size):
当我们进行一些特殊操
作如需要使用临时表才能完成的Order By,Group By 等等,MySQL 可能需要使用到临时表。当我们的临时表较小(小于
tmp_table_size参数所设置的大小)的时候,MySQL 会将临时表创建成内存临时表,只有当
tmp_table_size所设置的大小无法装下整个临时表的时候,MySQL 才会将该表创建成 MyISAM
存储引擎的表存放在磁盘上。不过,当另一个系统参数max_heap_table_size 的大小还小于 tmp_table_size
的时候,MySQL 将使用max_heap_table_size 参数所设置大小作为最大的内存临时表大小,而忽略 tmp_table_size
所设置的值。而且tmp_table_size 参数从 MySQL 5.1.2 才开始有,之前一直使用 max_heap_table_size。
上面所列举的 MySQL 线程独享内存仅仅只是所有线程独享内存中的部分,并不是全部,选择的原则是可能对 MySQL 的性能产生较大的影响,且可以通过系统参数进行调节。
由于以上内存都是线程独享,极端情况下的内存总体使用量将是所有连接线程的总倍数。所以各位朋友在设置过程中一定要谨慎,切不可为了提升性能就盲目的增大各参数值,避免因为内存不够而产生 Out Of Memory 异常或者是严重的 Swap 交换反而降低整体性能。
全局共享内存
全
局共享内主要是 MySQLInstance(mysqld进程)以及底层存储引擎用来暂存各种全局运算及可共享的暂存信息,如存储查询缓存的
QueryCache,缓存连接线程的 Thread Cache,缓存表文件句柄信息的 Table Cache,缓存二进制日志的
BinLogBuffer, 缓存 MyISAM 存储引擎索引键的 Key Buffer以及存储 InnoDB 数据和索引的 InnoDB
BufferPool 等等。下面针对 MySQL 主要的共享内存进行一个简单的分析。
查询缓存(Query Cache)
:
查询缓存是 MySQL 比较独特的一个缓存区域,用来缓存特定Query 的结果集(Result Set)信息,且共享给所有客户端。通过对
Query 语句进行特定的 Hash 计算之后与结果集对应存放在Query Cache 中,以提高完全相同的 Query
语句的相应速度。当我们打开 MySQL 的 Query Cache 之后,MySQL接收到每一个 SELECT 类型的 Query
之后都会首先通过固定的 Hash 算法得到该 Query 的 Hash 值,然后到 QueryCache 中查找是否有对应的 Query
Cache。如果有,则直接将 Cache的结果集返回给客户端。如果没有,再进行后续操作,得到对应的结果集之后将该结果集缓存到 Query
Cache中,再返回给客户端。当任何一个表的数据发生任何变化之后,与该表相关的所有 Query Cache 全部会失效,所以 Query
Cache对变更比较频繁的表并不是非常适用,但对那些变更较少的表是非常合适的,可以极大程度的提高查询效率,如那些静态资源表,配置表等等。为了尽可
能高效的利用 Query Cache,MySQL 针对 Query Cache 设计了多个 query_cache_type 值和两个
QueryHint:SQL_CACHE 和 SQL_NO_CACHE。当 query_cache_type 设置为0(或者
OFF)的时候不使用Query Cache,当设置为1(或者 ON)的时候,当且仅当 Query 中使用了 SQL_NO_CACHE 的时候
MySQL 会忽略Query Cache,当 query_cache_type 设置为2(或者DEMAND)的时候,当且仅当Query
中使用了SQL_CACHE 提示之后,MySQL 才会针对该 Query 使用 Query Cache。可以通过
query_cache_size来设置可以使用的最大内存空间。
连接线程缓存(Thread Cache)
:连接线程是
MySQL为了提高创建连接线程的效率,将部分空闲的连接线程保持在一个缓存区以备新进连接请求的时候使用,这尤其对那些使用短连接的应用程序来说可以极
大的提高创建连接的效率。当我们通过
thread_cache_size设置了连接线程缓存池可以缓存的连接线程的大小之后,可以通过(Connections -
Threads_created) /Connections * 100%
计算出连接线程缓存的命中率。注意,这里设置的是可以缓存的连接线程的数目,而不是内存空间的大小。
表缓存(Table Cache)
:
表缓存区主要用来缓存表文件的文件句柄信息,在MySQL5.1.3之前的版本通过 table_cache
参数设置,但从MySQL5.1.3开始改为 table_open_cache来设置其大小。当我们的客户端程序提交 Query 给 MySQL
的时候,MySQL 需要对 Query所涉及到的每一个表都取得一个表文件句柄信息,如果没有 Table Cache,那么
MySQL就不得不频繁的进行打开关闭文件操作,无疑会对系统性能产生一定的影响,Table Cache 正是为了解决这一问题而产生的。在有了
TableCache 之后,MySQL 每次需要获取某个表文件的句柄信息的时候,首先会到 Table
Cache中查找是否存在空闲状态的表文件句柄。如果有,则取出直接使用,没有的话就只能进行打开文件操作获得文件句柄信息。在使用完之后,MySQL会
将该文件句柄信息再放回 Table Cache池中,以供其他线程使用。注意,这里设置的是可以缓存的表文件句柄信息的数目,而不是内存空间的大小。
表定义信息缓存(Table definition Cache)
:
表定义信息缓存是从MySQL5.1.3 版本才开始引入的一个新的缓存区,用来存放表定义信息。当我们的
MySQL中使用了较多的表的时候,此缓存无疑会提高对表定义信息的访问效率。MySQL 提供了
table_definition_cache参数给我们设置可以缓存的表的数量。在 MySQL5.1.25 之前的版本中,默认值为128,从
MySQL5.1.25版本开始,则将默认值调整为 256
了,最大设置值为524288。注意,这里设置的是可以缓存的表定义信息的数目,而不是内存空间的大小。
二进制日志缓冲区(Binlog Buffer)
:
二进制日志缓冲区主要用来缓存由于各种数据变更操做所产生的Binary Log 信息。为了提高系统的性能,MySQL
并不是每次都是将二进制日志直接写入 Log File,而是先将信息写入Binlog Buffer 中,当满足某些特定的条件(如
sync_binlog参数设置)之后再一次写入 Log File 中。我们可以通过binlog_cache_size
来设置其可以使用的内存大小,同时通过 max_binlog_cache_size限制其最大大小(当单个事务过大的时候 MySQL
会申请更多的内存)。当所需内存大于 max_binlog_cache_size参数设置的时候,MySQL
会报错:“Multi-statement transaction required more
than‘max_binlog_cache_size’ bytes of storage”。
MyISAM索引缓存(Key Buffer)
:MyISAM 索引缓存将 MyISAM 表的索引信息缓存在内存中,以提高其访问性能。这个缓存可以说是影响 MyISAM 存储引擎性能的最重要因素之一了,通过 key_buffere_size 设置可以使用的最大内存空间。
InnoDB 日志缓冲区(InnoDB Log Buffer)
:
这是 InnoDB存储引擎的事务日志所使用的缓冲区。类似于 Binlog Buffer,InnoDB
在写事务日志的时候,为了提高性能,也是先将信息写入Innofb Log Buffer 中,当满足
innodb_flush_log_trx_commit参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件(或者同步到磁盘)中。可
以通过 innodb_log_buffer_size参数设置其可以使用的最大内存空间。
注:innodb_flush_log_trx_commit 参数对 InnoDB Log 的写入性能有非常关键的影响。该参数可以设置为0,1,2,解释如下:
-
0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file的刷新或者文件系统到磁盘的刷新操作;
-
1:在每次事务提交的时候将log buffer 中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;
-
2:事务提交会触发log buffer 到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。
此
外,MySQL文档中还提到,这几种设置中的每秒同步一次的机制,可能并不会完全确保非常准确的每秒就一定会发生同步,还取决于进程调度的问题。实际
上,InnoDB 能否真正满足此参数所设置值代表的意义正常 Recovery 还是受到了不同
OS下文件系统以及磁盘本身的限制,可能有些时候在并没有真正完成磁盘同步的情况下也会告诉 mysqld 已经完成了磁盘同步。
InnoDB 数据和索引缓存(InnoDB Buffer Pool)
:InnoDB
BufferPool 对 InnoDB 存储引擎的作用类似于 Key Buffer Cache 对 MyISAM
存储引擎的影响,主要的不同在于InnoDB Buffer Pool
不仅仅缓存索引数据,还会缓存表的数据,而且完全按照数据文件中的数据快结构信息来缓存,这一点和Oracle SGA 中的 database
buffer cache 非常类似。所以,InnoDB Buffer Pool 对 InnoDB存储引擎的性能影响之大就可想而知了。可以通过
(Innodb_buffer_pool_read_requests -Innodb_buffer_pool_reads) /
Innodb_buffer_pool_read_requests * 100%计算得到 InnoDB Buffer Pool 的命中率。
InnoDB 字典信息缓存(InnoDB Additional Memory Pool)
:InnoDB
字典信息缓存主要用来存放 InnoDB 存储引擎的字典信息以及一些 internal
的共享数据结构信息。所以其大小也与系统中所使用的InnoDB 存储引擎表的数量有较大关系。不过,如果我们通过
innodb_additional_mem_pool_size参数所设置的内存大小不够,InnoDB 会自动申请更多的内存,并在 MySQL 的
Error Log 中记录警告信息。
这里所列举的各种共享内存,是我个人认为对 MySQL 性能有较大影响的集中主要的共享内存。实际上,除了这些共享内存之外,MySQL 还存在很多其他的共享内存信息,如当同时请求连接过多的时候用来存放连接请求信息的back_log队列等。
以上内容可能存在分析不妥之处,欢迎各位朋友拍砖,一起交流。
分享到:
相关推荐
MySQL 内存使用调优 MySQL 的内存使用对性能至关重要。配置 MySQL 正确地使用内存基本上是肯定的。可以认为 MySQL 的内存消耗有两种范畴:可以控制的和不可控制的。你不能控制 MySQL 使用多少内存来运行服务器、...
本文将详细探讨MySQL内存使用中涉及的全局共享部分,如查询缓存(Query Cache)、表缓存(Table Cache)、线程缓存(Thread Cache)、二进制日志缓冲区(Binlog Buffer)以及InnoDB缓冲池(InnoDB Buffer Pool)等。...
MySQL内存使用的查看方式详解 在MySQL 5.7版本中,了解和监控内存使用是数据库管理的关键方面,有助于优化性能并防止资源耗尽。官方的`performance_schema`提供了丰富的工具来跟踪内存消耗。以下是几个关键的内存...
在优化MySQL内存使用时,重要的是要根据实际的数据库工作负载来调整上述参数,以确保既能提供足够的内存来处理请求,又能避免过度消耗系统资源。内存配置不当可能会导致性能瓶颈,如内存溢出或频繁的磁盘交换,这都...
## MySQL内存使用的关键指标及其监控 为了有效地监控MySQL的内存使用情况,我们需要了解并关注以下几个关键指标: ### 1. InnoDB Buffer Pool InnoDB Buffer Pool主要用于缓存InnoDB表的数据和索引,它极大地减少...
当用户遇到MySQL内存使用问题时,通常会怀疑是内存泄漏导致的,但实际情况可能并非如此。例如,有一个特定的bug(PS-5312),它展示了访问InnoDB全文索引时内存消耗增加的情况,但这并不等同于内存泄漏。 InnoDB...
在 MySQL 中,线程独享内存主要用于各客户端连接线程存储各种操作的独享数据,如线程栈信息,分组排序操作,数据读写缓冲,结果集暂存等等,而且大多数可以通过相关参数来控制内存的使用量。 线程栈信息使用内存...
这些参数控制着不同操作的内存使用,如排序、连接、读取和临时表。根据工作负载的特点,可以适当调整它们以优化性能,例如,处理大量JOIN操作时,增大`join_buffer_size`可能有所帮助。 在调整这些参数时,需要...
MySQL内存统计的分析与实践是数据库管理员(DBA)在日常工作中必须掌握的一项关键技能。内存管理对于MySQL数据库的性能有着深远影响,而有效地分析和理解内存使用情况可以帮助优化数据库性能,预防并解决内存溢出等...
一张图弄清mysql内存结构,内存中都有什么,多mysql原理及后续问题排查、优化很有帮助,推荐给大家
首先,了解MySQL内存使用的几个关键组件是必要的。其中包括: 1. **缓冲池(Buffer Pool)**:这是MySQL用来缓存表数据和索引的主要内存区域,以减少磁盘I/O。默认情况下,MySQL可能分配较大的内存空间来容纳缓冲池...
在进行MySQL内存分析时,首先需要了解MySQL的内存结构和工作机制,这对于优化MySQL的性能至关重要。内存分配问题在容量规划阶段常常被提出,人们会疑惑应该为MySQL以及整个系统分配多少内存。通常互联网上有许多不...
### MySQL内存数据库详解 在探讨MySQL的内存数据库之前,我们首先需要理解什么是内存数据库。内存数据库,顾名思义,是一种主要依靠系统主存而非硬盘存储数据的数据库管理系统。这种设计使得内存数据库在处理速度上...
本文主要讨论的是MySQL中的全局缓存和线程缓存的使用情况,这两个部分占据了内存使用的主要部分。 首先,我们要理解全局缓存的概念。全局缓存主要包括以下几个部分: 1. `key_buffer_size`:这是MyISAM表的索引...
echo "警告:MySQL内存使用率超过90%!" | mail -s "MySQL告警" admin@example.com fi # 更多监控项... ``` 上述脚本检查了MySQL的连接数和内存使用率,当达到预设阈值时,会通过邮件发送告警。实际应用中,脚本...
### MySQL优化中的内存计算公式详解 ...通过对MySQL内存计算公式的理解与应用,不仅可以有效控制内存使用,还能确保数据库在高负载下稳定运行。希望本文能为您的MySQL优化工作提供一定的参考价值。
vps的内存为512M,安装好nginx,php等启动起来,mysql死活启动不起来看了日志只看到对应pid被结束了,后跟踪看发现是内存不足被killed;mysql5.6启动内存占用过高怎么办呢,下面小编给大家解答下
通常我们会添加对内存的监控报警,例如:当memory或swap使用超过90%时,触发报警通知,需要及时介入排查。 如果已经出现OOM,则可以通过dmesg命令查看,CentOS7版本以上支持 -T选项,能将时间戳转成时