计算mysql内存使用

计算mysql内存使用

mysqlused mem =key_buffer_size + query_cache_size

+innodb_buffer_pool_size + innodb_additional_mem_pool_size

+innodb_log_buffer_size

+max_connections * (

read_buffer_size+ read_rnd_buffer_size

+sort_buffer_size+ join_buffer_size

+binlog_cache_size + thread_stack+ tmp_table_size

)

 

分为两部分:线程独享内存+全局共享内存

 

线程独享内存= key_buffer_size + query_cache_size

+ innodb_buffer_pool_size +innodb_additional_mem_pool_size

+ innodb_log_buffer_size

 

 

全局共享内存= read_buffer_size +read_rnd_buffer_size

+ sort_buffer_size+join_buffer_size

+ binlog_cache_size +thread_stack+ tmp_table_size

 

1、 key_buffer_size:决定索引处理的速度,尤其是索引读的速度。默认值是16M,通过检查状态值Key_read_requests和Key_reads,可以知道key_buffer_size设置是否合理。比例key_reads /key_read_requests应该尽可能的低,至少是1:100,1:1000更好(上述状态值可以使用'key_read%'获得用来显示状态数据)。key_buffer_size只对MyISAM表起作用。即使你不使用MyISAM表,但是内部的临时磁盘表是MyISAM表,也要使用该值。可以使用检查状态值'created_tmp_disk_tables'得知详情。

2、 innodb_buffer_pool_size:InnoDB使用该参数指定大小的内存来缓冲数据和索引,这个是Innodb引擎中影响性能最大的参数。

3、 innodb_additional_mem_pool_size:指定InnoDB用来存储数据字典和其他内部数据结构的内存池大小。缺省值是8M。通常不用太大,只要够用就行,应该与表结构的复杂度有关系。如果不够用,MySQL会在错误日志中写入一条警告信息(已经不用了 )

4、 innodb_log_buffer_size:指定InnoDB用来存储日志数据的缓存大小,如果您的表操作中包含大量并发事务(或大规模事务),并且在事务提交前要求记录日志文件,请尽量调高此项值,以提高日志效率。

5、 query_cache_size:是MySQL的查询缓冲大小。(从4.0.1开始,MySQL提供了查询缓冲机制)使用查询缓冲,MySQL将SELECT语句和查询结果存放在缓冲区中,今后对于同样的SELECT语句(区分大小写),将直接从缓冲区中读取结果。根据MySQL用户手册,使用查询缓冲最多可以达到238%的效率。通过检查状态值'Qcache_%',可以知道query_cache_size设置是否合理:如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲不够的情况,如果Qcache_hits的值也非常大,则表明查询缓冲使用非常频繁,此时需要增加缓冲大小;如果Qcache_hits的值不大,则表明你的查询重复率很低,这种情况下使用查询缓冲反而会影响效率,那么可以考虑不用查询缓冲。此外,在SELECT语句中加入SQL_NO_CACHE可以明确表示不使用查询缓冲。

 

线程缓存

每个连接到MySQL服务器的线程都需要有自己的缓冲。大概需要立刻分配256K,甚至在线程空闲时,它们使用默认的线程堆栈,网络缓存等。事务开始之后,则需要增加更多的空间。运行较小的查询可能仅给指定的线程增加少量的内存消耗,然而如果对数据表做复杂的操作例如扫描、排序或者需要临时表,则需分配大约read_buffer_size,sort_buffer_size,read_rnd_buffer_size,tmp_table_size大小的内存空间。不过它们只是在需要的时候才分配,并且在那些操作做完之后就释放了。有的是立刻分配成单独的组块。tmp_table_size 可能高达MySQL所能分配给这个操作的最大内存空间了

 

1、 read_buffer_size:是MySQL读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySQL会为它分配一段内存缓冲区。read_buffer_size变量控制这一缓冲区的大小。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能。

2、 sort_buffer_size:是MySQL执行排序使用的缓冲大小。如果想要增加ORDER BY的速度,首先看是否可以让MySQL使用索引而不是额外的排序阶段。如果不能,可以尝试增加sort_buffer_size变量的大小。

3、 read_rnd_buffer_size:是MySQL的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySQL会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySQL会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。

4、 tmp_table_size:是MySQL的临时表缓冲大小。所有联合在一个DML指令内完成,并且大多数联合甚至可以不用临时表即可以完成。大多数临时表是基于内存的(HEAP)表。具有大的记录长度的临时表 (所有列的长度的和)或包含BLOB列的表存储在硬盘上。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自动将内存中的heap表改为基于硬盘的MyISAM表。还可以通过设置tmp_table_size选项来增加临时表的大小。也就是说,如果调高该值,MySQL同时将增加heap表的大小,可达到提高联接查询速度的效果。

 

临时表使用内存(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。

 

5、 thread_stack :主要用来存放每一个线程自身的标识信息,如线程id,线程运行时基本信息等等,我们可以通过 thread_stack 参数来设置为每一个线程栈分配多大的内存。

6、 join_buffer_size:应用程序经常会出现一些两表(或多表)Join的操作需求,MySQL在完成某些 Join 需求的时候(all/index join),为了减少参与Join的“被驱动表”的读取次数以提高性能,需要使用到 Join Buffer 来协助完成 Join操作。当 Join Buffer 太小,MySQL 不会将该 Buffer 存入磁盘文件,而是先将Join Buffer中的结果集与需要 Join 的表进行 Join 操作,然后清空 Join Buffer 中的数据,继续将剩余的结果集写入此 Buffer 中,如此往复。这势必会造成被驱动表需要被多次读取,成倍增加 IO 访问,降低效率。

7、 binlog_cache_size:在事务过程中容纳二进制日志SQL 语句的缓存大小。二进制日志缓存是服务器支持事务存储引擎并且服务器启用了二进制日志(—log-bin 选项)的前提下为每个客户端分配的内存,注意,是每个Client 都可以分配设置大小的binlog cache 空间。如果系统中经常会出现多语句事务的话,可以尝试增加该值的大小,以获得更好的性能。当然,我们可以通过MySQL 的以下两个状态变量来判断当前的binlog_cache_size 的状况:Binlog_cache_use 和Binlog_cache_disk_use。“max_binlog_cache_size”:和"binlog_cache_size"相对应,但是所代表的是binlog 能够使用的最大cache 内存大小。当我们执行多语句事务的时候,max_binlog_cache_size 如果不够大的话,系统可能会报出“ Multi-statement transactionrequired more than 'max_binlog_cache_size' bytes ofstorage”的错误。

8、 其中需要注意的是:table_cache表示的是所有线程打开的表的数目,和内存无关。

 

1、http://imysql.cn/node/97:mysql服务器内存使用

Every so often people ask me the questionhow should they estimate memory consumption by MySQL Server in givenconfiguration. What is the formula they could use.

 

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

 

Thereasons to worry about memory usage are quite understandable. If you configureMySQL Server so it uses too small amount of memory it will likey performsuboptimally. If you however configure it so it consumes too much memory it maybe crashing , failing to execute queries or make operation to swap seriouslyslowing down. On now legacy 32bit platforms you could also run out of addressspace so that had to be watched as well.

Havingsaid so, I do not think looking for the secret fomula to compute your possiblememory usage is the right approach to this problem. The reasons are - thisformula is very complex nowadays and what is even more important “theoreticallypossible” maximum it provides have nothing to do with real memory consumptions.In fact typical server with 8GB of memory will often run with maximumtheoretical memory usage of 100GB or more. Furthermore there is no easy“overcommit factor” you can use - it really depends on application andconfiguration. Some applications will drive server to 10% of theoretical memoryconsumptions others only to 1%.

 

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

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

 

Sowhat could you do instead ? First take a look at global buffers which areallocated at start and always where - these are key_buffer_size,innodb_buffer_pool_size, innodb_additional_memory_pool_size,innodb_log_buffer_size, query_cache_size. If you’re using MyISAM seriously youcan also add the size of Operation System cache you would like MySQL to use foryour table. Take this number add to it number of memory Operation System andother applications need, add might be 32MB more for MySQL Server code andvarious small static buffers. This is memory which you can consider used whenyou just start MySQL Server. The rest of memory is available for connections.For exampe with 8GB server you might have everything listed adding up to 6GB,so you have 2GB left for your threads.

 

那么,我们可以做什么呢?首先,来看看那些在启动时就需要分配并且总是存在的全局缓冲 -- 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内存则留下来给线程使用。

 

Eachthread connecting to MySQL server will needs its own buffers. About 256K isallocated at once even if thread is idle - they are used by default threadstack, net buffer etc. If transaction is started some more space can add up.Running small queries might only barely increase memory consumption for giventhread, however if table will perform complex operations such as full tablescans, sorts, or need temporary tables as much as read_buffer_size, sort_buffer_size,read_rnd_buffer_size, tmp_table_size of memory might be allocated. But theyare only allocated upon the need and freed once given stage of query is done.Some of them are allocated as single chunk at once others, for exampletmp_table_size is rather maximum amount of memory MySQL will allocate for thisoperation. Note it is more complicated than once may think - multiple buffersof the same type might be allocated for exampe to handle subqueries. For somespecial queries memory usage might be even larger - bulk inserts may allocatebulk_insert_buffer_size bytes of memory if done to MyISAM tables.myisam_sort_buffer_size used for ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLEcommands.

 

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

 

ForOLTP applications with simple queries memory consumption is often less than 1MBper thread with default buffers, and you really do not need to increase perthread buffers unless you have complex queries. Sorting 10 rows will be as fastwith 1MB sort buffer as with 16MB (actually 16MB might be even slower but it isother story).

 

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

 

Anotherapproach you may take is to come up with amount of memory you want MySQL Serverto consume at peak. This can be easily computed by memory needed for OS, FileCache and other applications. For 32bit envinronment you also should keep 32bitlimits into account and probably limit “mysqld” size to about 2.5GB (exactnumber depens on a lot of factors). Now you can use “ps aux” to see VSZ -Virtual Memory allocated by MySQL process. You can also look at “ResidentMemory” but I find it less helpful as it may down because of swapping - notwhat you would like to see. Monitor how the value changes so you know memoryrequirements with current settings and increase/decrease values appropriately.

 

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

 

Somemay say, Hey we want to have 100% guarantee our server will never run out ofmemory, no matter which queries or users will decide to run. Unfortunately thisis as much close to impossible to be impractical. Here is why:

 

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

 

List of rarely considered MySQL ServerMemory Requirements

 

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

 

1、 Thread buffers can be allocated more than once for each thread. Considerfor example subqueries - each layer may need its own read_buffer,sort_buffer,tmp_table_size etc

 

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

2、 Many variabes can be set per connection. So you can’t relay on global valuesif developers may use their local values to run some queries.

 

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

 

3、 There can be mutiple key caches. Multiple key caches can be created toaccomodate query executions

 

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

4、 Query Parsing and optimization needs memory. This is usually small to beignored but certain queries can have very large memory requrement for thisstep, especially specially crafted ones.

 

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

5、 Stored Procedures. Compex stored procedures may require a lot of memory

 

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

6、 Prepared statements and Cursors. Single connection may have manyprepared statements and cursors. Their number finally can be limited but eachof them still can have very large memory consumption

 

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

7、 Innodb Table Cache. Innodb has its own table cache in which meta dataabout each table accessed from the start is stored. It is never purged and maybe large if you have a lot of tables. It also means user having CREATE TABLEprivilege should be able to run MySQL server out of memory

 

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

8、 MyISAM buffers. MyISAM may allocate buffer which is large enough tocontain largest record in the given table which is held until table is closed.

 

MyISAM缓冲。 MyISAM表可能会分配一个足以装下指定表最大记录的缓冲,而且这个缓冲直到表关闭了才释放。

9、 Federated Storage Engine. This may have unbound memory requirementsretriving result sets from remove queries.

FEDERATED存储引擎。 This may have unboundmemory requirements retriving result sets from remove queries.

10、Blobs may require 3x timeof memory. This is important if you’re deaing with large Blobs (your max_allowed_packetis large) Processing of 256MB of blob may require 768MB of memory.

Blobs可能需要3倍的内存。 这在处理很大(max_allowed_packet 的值较大)的Blobs数据时很重要,如果处理256MB的数据可能需要768MB的内存。

11、Storage Engines. In generalstorage engines may have their own per thread or global memory allocationswhich are not tuned as buffers. Watch for these especially now with manystorage engines being released for MySQL by various parties.

存储引擎。通常情况下,存储引擎会设置自己的每个线程的全局分配内存,它通常不能像缓存一样可以调节。现在应该通过各种方式来特别关注MySQL释放出来的存储引擎。

 

Ido not pretend this to be complete list. On the contrary I’m quite sure I’vemissed something (drop me a note if you have something to add). But the mainpoint is - there are a lot of memory consumers out where and trying to findpeak possible usage for each is impractical - so my advice would be measurewhat you get in practice and how memory consumption reacts to changing variousvariables. For example you may find out increasing sort_buffer_size from 1MB to4MB and 1000 max_connections increases peak memory consumption just 30MB not3000MB as you might have counted.

 

我想这还不是完成的列表,相反地,我觉得还是漏掉了一些(如果你知道,请给我回复加上)。但主要的原因是 -- 找到每次内存消耗峰值是不切实际的,因此我的这些建议可以用来衡量一下你实际修改一些变量值产生的反应。例如,把 sort_buffer_size 从1MB增加到4MB并且在 max_connections 为 1000 的情况下,内存消耗增长峰值并不是你所计算的3000MB而是30MB。


 [zy1]不止是myisam表吧?

 

 

批量插入暂存使用内存(bulk_insert_buffer_size):当我们使用如 insert … values(…),(…),(…)… 的方式进行批量插入的时候,MySQL 会先将提交的数据放如一个缓存空间中,当该缓存空间被写满或者提交完所有数据之后,MySQL 才会一次性将该缓存空间中的数据写入数据库并清空缓存。此外,当我们进行 LOAD DATA INFILE 操作来将文本文件中的数据 Load 进数据库的时候,同样会使用到此缓冲区

你可能感兴趣的:(MySQL源码分析)