经常有人问配置mysql时该如何估算内存的消耗。那么该使用什么公式来计算呢?

  关心内存怎么使用的原因是可以理解的。如果配置mysql服务器使用太少的内存会导致性能不是最优的;如果配置了太多的内存则会导致崩溃,无法执行查询或者导致交换操作严重变慢。在现在的32位平台下,仍有可能把所有的地址空间都用完了,因此需要监视着。

  话虽如此,但我并不觉得找到什么可以计算内存使用的秘诀公式就能很好地解决这个问题。原因有--如今这个公式已经很复杂了,更重要的是,通过它计算得到的值只是“理论可能”并不是真正消耗的值。事实上,有8gb内存的常规服务器经常能运行到最大的理论值--100gb甚至更高。此外,你轻易不会使用到“超额因素”--它实际上依赖于应用以及配置。一些应用可能需要理论内存的10%而有些仅需1%。

  那么,我们可以做什么呢?首先,来看看那些在启动时就需要分配并且总是存在的全局缓冲--key_buffer_size,innodb_buffer_pool_size,innodb_additional_memory_pool_size,innodb_log_buffer_size,query_cache_size。如果你大量地使用myisam表,那么你也可以增加操作系统的缓存空间使得mysql也能用得着。把这些也都加到操作系统和应用程序所需的内存值之中,可能需要增加32mb甚至更多的内存给mysql服务器代码以及各种不同的小静态缓冲。这些就是你需要考虑的在mysql服务器启动时所需的内存。其他剩下的内存用于连接。例如有8gb内存的服务器,可能监听所有的服务就用了6gb的内存,剩下的2gb内存则留下来给线程使用。

  和"mysql服务器内存使用"有关的数据库编程小帖士:

  strong>SUBSTRB

  SUBSTRB返回一字符串的指定部分。2881064151该函数与SUBSTR极为类似,只是该函数的start和length两参数均以字节为单位,而不是根据字符。这种区别只有在使用多种不同的字符集时才有意义。

  每个连接到mysql服务器的线程都需要有自己的缓冲。大概需要立刻分配256k,甚至在线程空闲时--它们使用默认的线程堆栈,网络缓存等。事务开始之后,则需要增加更多的空间。运行较小的查询可能仅给指定的线程增加少量的内存消耗,然而如果对数据表做复杂的操作例如扫描、排序或者需要临时表,则需分配大约read_buffer_size,sort_buffer_size,read_rnd_buffer_size,tmp_table_size大小的内存空间。不过它们只是在需要的时候才分配,并且在那些操作做完之后就释放了。有的是立刻分配成单独的组块,例如tmp_table_size可能高达mysql所能分配给这个操作的最大内存空间了。注意,这里需要考虑的不只有一点--可能会分配多个同一种类型的缓存,例如用来处理子查询。一些特殊的查询的内存使用量可能更大--如果在myisam表上做成批的插入时需要分配bulk_insert_buffer_size大小的内存。执行alter table,optimize table,repair table命令时需要分配myisam_sort_buffer_size大小的内存。

  只有简单查询oltp应用的内存消耗经常是使用默认缓冲的每个线程小于1mb,除非需要使用复杂的查询否则无需增加每个线程的缓冲大小。使用1mb的缓冲来对10行记录进行排序和用16mb的缓冲基本是一样快的(实际上16mb可能会更慢,不过这是其他方面的事了)。

  另外,就是找出mysql服务器内存消耗的峰值。这很容易就能计算出操作系统所需的内存、文件缓存以及其他应用。在32位环境下,还需要考虑到32位的限制,限制“mysqld”的值大约为2.5g(实际上还要考虑到很多其他因素)。2881064151现在运行“ps aux”命令来查看vsz的值--mysql进程分配的虚拟内存。也可以查看“resident memory”的值,不过我想它可能没多大用处,因为它会由于交换而变小--这并不是你想看到的。监视着内存变化的值,就能知道是需要增加/减少当前的内存值了。

  可能有的人想说,我们想要让服务器能保证100%不会耗尽内存,不管决定用什么样的查询、什么样的用户。很不幸,这其实很不明智也不可能,因为:

  以下是很少考虑的mysql服务器内存需求

  每个线程可能会不止一次需要分配缓冲。考虑到例如子查询--每层都需要有自己的read_buffer,sort_buffer,tmp_table_size等。

  在每个连接中很多变量都可能需要重新设置。如果开发者想设定自己的变量值来运行某些查询就不能继续使用全局值。

  可能有多个索引缓存。为了配合执行查询可能会创建多个索引缓存。

  解析查询和优化都需要内存。这些内存通常比较小,可以忽略,不过如果是某些查询在这个步骤中则需要大量内存,尤其是那些设计的比较特别的查询。

  存储过程。复杂的存储过程可能会需要大量内存。

  准备查询语句以及游标。单次链接可能会有很多的准备好的语句以及游标。它们的数量最后可以限定,但是仍然会消耗大量的内存。

  innodb表缓存。innnodb表有自己的缓存,它保存了从一开始访问每个表的元数据。它们从未被清除过,如果有很多innodb表的话,那么这个量就很大了。这也就意味着拥有create table权限的用户就可能把mysql服务器的内存耗尽。