对于任何一个数据库管理系统来讲,内存的分配使用绝对能够算的上是其核心之一了,因此不少但愿更为深刻了解某数据库管理系统的人,都会但愿一窥究竟,我也不例外。php
这里给出方案html
按照下面的设置试试看:mysql
key_buffer_size= 3840M
max_allowed_packet = 16M
table_cache = 1024
sort_buffer_size = 32M
read_buffer_size = 32M
read_rnd_buffer_size = 32M
myisam_sort_buffer_size = 256M
thread_cache_size = 32
query_cache_size = 256M
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8算法
其中key_buffer_size 上限是 4G,不能再多了。sql
可是实际的为了使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队列等。
参考:http://waynerqiu.com/7/57.html
延伸阅读: