zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

MySQL全局共享内存介绍

mysql 介绍 全局 共享内存
2023-06-13 09:15:31 时间

前言

全局共享内存则主要是MySQLInstance(mysqld进程)以及底层存储引擎用来暂存各种全局运算及可共享的暂存信息,如存储查询缓存的QueryCache,缓存连接线程的ThreadCache,缓存表文件句柄信息的TableCache,缓存二进制日志的BinLogBuffer,缓存MyISAM存储引擎索引键的KeyBuffer以及存储InnoDB数据和索引的InnoDBBufferPool等等。下面针对MySQL主要的共享内存进行一个简单的分析。

查询缓存(QueryCache)

查询缓存是MySQL比较独特的一个缓存区域,用来缓存特定Query的结果集(ResultSet)信息,且共享给所有客户端。通过对Query语句进行特定的Hash计算之后与结果集对应存放在QueryCache中,以提高完全相同的Query语句的相应速度。当我们打开MySQL的QueryCache之后,MySQL接收到每一个SELECT类型的Query之后都会首先通过固定的Hash算法得到该Query的Hash值,然后到QueryCache中查找是否有对应的QueryCache。如果有,则直接将Cache的结果集返回给客户端。如果没有,再进行后续操作,得到对应的结果集之后将该结果集缓存到QueryCache中,再返回给客户端。当任何一个表的数据发生任何变化之后,与该表相关的所有QueryCache全部会失效,所以QueryCache对变更比较频繁的表并不是非常适用,但对那些变更较少的表是非常合适的,可以极大程度的提高查询效率,如那些静态资源表,配置表等等。为了尽可能高效的利用QueryCache,MySQL针对QueryCache设计了多个query_cache_type值和两个QueryHint:SQL_CACHE和SQL_NO_CACHE。当query_cache_type设置为0(或者OFF)的时候不使用QueryCache,当设置为1(或者ON)的时候,当且仅当Query中使用了SQL_NO_CACHE的时候MySQL会忽略QueryCache,当query_cache_type设置为2(或者DEMAND)的时候,当且仅当Query中使用了SQL_CACHE提示之后,MySQL才会针对该Query使用QueryCache。可以通过query_cache_size来设置可以使用的最大内存空间。

连接线程缓存(ThreadCache)

连接线程是MySQL为了提高创建连接线程的效率,将部分空闲的连接线程保持在一个缓存区以备新进连接请求的时候使用,这尤其对那些使用短连接的应用程序来说可以极大的提高创建连接的效率。当我们通过thread_cache_size设置了连接线程缓存池可以缓存的连接线程的大小之后,可以通过(Connections-Threads_created)/Connections*100%计算出连接线程缓存的命中率。注意,这里设置的是可以缓存的连接线程的数目,而不是内存空间的大小。

表缓存(TableCache)

表缓存区主要用来缓存表文件的文件句柄信息,在MySQL5.1.3之前的版本通过table_cache参数设置,但从MySQL5.1.3开始改为table_open_cache来设置其大小。当我们的客户端程序提交Query给MySQL的时候,MySQL需要对Query所涉及到的每一个表都取得一个表文件句柄信息,如果没有TableCache,那么MySQL就不得不频繁的进行打开关闭文件操作,无疑会对系统性能产生一定的影响,TableCache正是为了解决这一问题而产生的。在有了TableCache之后,MySQL每次需要获取某个表文件的句柄信息的时候,首先会到TableCache中查找是否存在空闲状态的表文件句柄。如果有,则取出直接使用,没有的话就只能进行打开文件操作获得文件句柄信息。在使用完之后,MySQL会将该文件句柄信息再放回TableCache池中,以供其他线程使用。注意,这里设置的是可以缓存的表文件句柄信息的数目,而不是内存空间的大小。

表定义信息缓存(TabledefinitionCache)

表定义信息缓存是从MySQL5.1.3版本才开始引入的一个新的缓存区,用来存放表定义信息。当我们的MySQL中使用了较多的表的时候,此缓存无疑会提高对表定义信息的访问效率。MySQL提供了table_definition_cache参数给我们设置可以缓存的表的数量。在MySQL5.1.25之前的版本中,默认值为128,从MySQL5.1.25版本开始,则将默认值调整为256了,最大设置值为524288。注意,这里设置的是可以缓存的表定义信息的数目,而不是内存空间的大小。

二进制日志缓冲区(BinlogBuffer)

二进制日志缓冲区主要用来缓存由于各种数据变更操做所产生的BinaryLog信息。为了提高系统的性能,MySQL并不是每次都是将二进制日志直接写入LogFile,而是先将信息写入BinlogBuffer中,当满足某些特定的条件(如sync_binlog参数设置)之后再一次写入LogFile中。我们可以通过binlog_cache_size来设置其可以使用的内存大小,同时通过max_binlog_cache_size限制其最大大小(当单个事务过大的时候MySQL会申请更多的内存)。当所需内存大于max_binlog_cache_size参数设置的时候,MySQL会报错:“Multi-statementtransactionrequiredmorethan‘max_binlog_cache_size"bytesofstorage”。

MyISAM索引缓存(KeyBuffer)

MyISAM索引缓存将MyISAM表的索引信息缓存在内存中,以提高其访问性能。这个缓存可以说是影响MyISAM存储引擎性能的最重要因素之一了,通过key_buffere_size设置可以使用的最大内存空间。

InnoDB日志缓冲区(InnoDBLogBuffer)

这是InnoDB存储引擎的事务日志所使用的缓冲区。类似于BinlogBuffer,InnoDB在写事务日志的时候,为了提高性能,也是先将信息写入InnofbLogBuffer中,当满足innodb_flush_log_trx_commit参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件(或者同步到磁盘)中。可以通过innodb_log_buffer_size参数设置其可以使用的最大内存空间。
注:innodb_flush_log_trx_commit参数对InnoDBLog的写入性能有非常关键的影响。该参数可以设置为0,1,2,解释如下:
*0:logbuffer中的数据将以每秒一次的频率写入到logfile中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何logbuffer到logfile的刷新或者文件系统到磁盘的刷新操作;
*1:在每次事务提交的时候将logbuffer中的数据都会写入到logfile,同时也会触发文件系统到磁盘的同步;
*2:事务提交会触发logbuffer到logfile的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。

此外,MySQL文档中还提到,这几种设置中的每秒同步一次的机制,可能并不会完全确保非常准确的每秒就一定会发生同步,还取决于进程调度的问题。实际上,InnoDB能否真正满足此参数所设置值代表的意义正常Recovery还是受到了不同OS下文件系统以及磁盘本身的限制,可能有些时候在并没有真正完成磁盘同步的情况下也会告诉mysqld已经完成了磁盘同步。

InnoDB数据和索引缓存(InnoDBBufferPool)

InnoDBBufferPool对InnoDB存储引擎的作用类似于KeyBufferCache对MyISAM存储引擎的影响,主要的不同在于InnoDBBufferPool不仅仅缓存索引数据,还会缓存表的数据,而且完全按照数据文件中的数据快结构信息来缓存,这一点和OracleSGA中的databasebuffercache非常类似。所以,InnoDBBufferPool对InnoDB存储引擎的性能影响之大就可想而知了。可以通过(Innodb_buffer_pool_read_requests-Innodb_buffer_pool_reads)/Innodb_buffer_pool_read_requests*100%计算得到InnoDBBufferPool的命中率。

InnoDB字典信息缓存(InnoDBAdditionalMemoryPool)

InnoDB字典信息缓存主要用来存放InnoDB存储引擎的字典信息以及一些internal的共享数据结构信息。所以其大小也与系统中所使用的InnoDB存储引擎表的数量有较大关系。不过,如果我们通过innodb_additional_mem_pool_size参数所设置的内存大小不够,InnoDB会自动申请更多的内存,并在MySQL的ErrorLog中记录警告信息。

这里所列举的各种共享内存,是我个人认为对MySQL性能有较大影响的集中主要的共享内存。实际上,除了这些共享内存之外,MySQL还存在很多其他的共享内存信息,如当同时请求连接过多的时候用来存放连接请求信息的back_log队列等。

以上内容可能存在分析不妥之处,欢迎各位朋友拍砖,一起交流。