概述很多朋友可能对Innodb如何使用内存有很多疑问。这里先简单介绍一下innodb的内存结构,然后结合innodb启动时的分配情况进行说明。1.INNODB内存结构(1)聚簇索引与非聚簇索引:聚簇索引:主键,有序,存储顺序与内存一致非聚簇索引:非主键,无序聚簇索引将表中的数据存储在叶节点聚集索引将主键和索引列存储在叶节点中。使用非聚集索引查询数据时,获取叶子上的主键,然后找到要查找的数据。(获取主键再查找的过程称为回表)(2)缓冲池:缓冲池用于存放各种数据缓存。Innodb总是将磁盘(数据库文件)中的数据按页(16K)读取到缓冲池中,然后按照最近最少使用算法(LRU)将数据保存到缓冲池中。如果数据库文件需要修改,总是先修改缓冲池中的页(修改后的页为脏页),然后以一定的频率刷新到磁盘。(3)插入缓冲区(insertbuffer):使用条件:1.该索引为辅助索引;2.索引不唯一。也就是说,主键索引不使用插入缓冲。主键索引是聚簇索引,插入是顺序的,执行效率比较高,不需要缓冲。但是,当表中有辅助索引(非聚集索引,非主键)时,不一定是顺序的。这时需要离散访问,插入性能会降低。因此,非聚集索引的插入和更新操作并不是直接插入到索引页中,而是插入到缓冲区中,然后在插入缓冲区和非聚集索引的叶子节点进行合并操作一定的频率。注意:由于非主键索引的叶子节点存放的是主键和当前列的值,所以在使用非聚集索引查询时,先查辅助索引的树找到对应的主键,再查主键索引树。二是效率不高。(4)重做日志(redolog):事务提交时,Innodb会先从磁盘读取数据到内存进行修改,然后将事务日志写入日志缓冲区(logbuffer),然后刷新到重做日志文件(redologfile)被持久化,然后定期刷新到磁盘。用于在实例恢复时继续已经提交但数据还没有完全写回磁盘的事务。(5)doublewrite(两次写入):为了防止redolog在写入过程中被损坏,我们需要保留一个备份。如果发生故障,首先从备份中恢复重做日志,然后再进行数据恢复。(6)undolog:记录数据修改前的镜像,用于将未提交的事务回滚到事务开始前的状态。撤销操作:当Innodb存储引擎回滚时,实际上是在做与上一个相关的工作。对于插入操作,Innodb会完成一次删除。对于更新,它会执行反向更新,将修改前的行放回去。(7)自适应哈希索引:Innodb会监控索引对表的搜索频率,如果发现建立哈希索引会提高速度,则会自动创建哈希索引。不是索引整个表,而是根据访问频率创建某些页面。(8)事务提交:在事务过程中,每执行一条SQL语句,都会记录undolog和redolog,然后更新数据,形成脏页。然后根据时间或空间条件flushredologs,根据checkpointsflushundologs和dirtypages,flush后可以删除对应的redologs。此时事务还没有提交。如果发生crash,首先查看checkpoint记录,使用对应的redolog恢复数据和undolog,然后查看undolog的状态,发现事务还没有提交,然后使用undolog来恢复回滚。当一个事务执行commit操作时,所有与该事务相关的重做日志都会被放到磁盘上。只有所有的redolog都成功的落盘了才算commit成功。然后内存中的数据脏页继续根据checkpoint进行flush。如果这时候发生crash,就只有redolog来恢复数据了。2.一些重要的概念:NBLOCKS=Innodb_buffer_poolhasmultiplepages(block)=innodb_buffer_pool_size/16384(16k)OS_THREADS=if(innodb_buffer_pool_size>=1000Mb)=50000elseif(innodb_buffer_pool_size>0=800else)=该值仅用于*nixes系统,Windows有一点区别(OS_THREADS)3.Innodb使用的内存包括:innodb_buffer_pool_sizeinnodb_additional_mem_pool_sizeinnodb_log_buffer_sizeadaptiveindexhash,size(innodbbufferindexmanagementarea)=innodb_buffer_pool_size/64system,dictionaryhashsize(innodb内部字典)area)=6*innodb_buffer_pool_size/512memoryforsync_array,size(overheadforsyncronzationinsideInnodb)=OS_THREAD*512memoryforos_event,size(overheadforsyncronzationofinnodbmemory)=OS_THREAD*216memoryforlockingsystem(内存锁管理系统)),大小=5*4*NBBLOCKS4。innodb内存占用的计算公式为:Innodb_buffer_pool_size+innodb_log_buffer_size+innodb_additional_mem_pool_size+812/16384*innodb_buffer_pool_size+OS_THREADS*368for812_THREADS*368for812_bpools*只需使用innodb_buffer_pool_size/20 计算,对于OS_THREADS*368OS_THREADS*368=17.5MBifinnodb_buffer_pool_size>1000MBOS_THREADS*3368=3.5MBifinnodb_buffer_pool_size>8MB举一个例子:如果你的innodb_buffer_pool_size有1500MB,innodb_additional_mem_pool_size=20MB,innodb_log_buffer_size=8M,Innodb将会向系统申请Memory=1500M+20M+8M+1500/20M+17.5=1620.5MAccordingtotheaboveconditions,wecancalculatehowmuchmemoryInnodbneedsmostfundamentally,sothatwecanalsohaveaplanforthememoryusageoftheserver
