innodb内存管理

1.InnoDB内存管理分配采用内存堆方式,从内存池申请和innodb buffer pool申请,按照不同的内存类型采用不同内存分配。
    在innodb内存管理中有三种内存类型:
    (1)动态内存,该内存是从内存池中进行申请.
    (2)缓冲内存,该内存是从buffer pool中进行分配
    (3)特殊情景下的内存。
    如下定义了三种内存类型:

    #define MEM_HEAP_DYNAMIC    0    /* the most common type */
    #define MEM_HEAP_BUFFER        1
    #define MEM_HEAP_BTR_SEARCH    2    

    typedef struct mem_block_info_t    mem_block_t;

    /* A memory heap is a nonempty linear list of memory blocks */
    typedef mem_block_t        mem_heap_t;

    代码:
            if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {
                    assert(type == MEM_HEAP_DYNAMIC || n <= MEM_MAX_ALLOC_IN_BUF);
                    block = static_cast<mem_block_t*>(mem_area_alloc(&len, mem_comm_pool));
                }
            else
                {
                    buf_block = buf_block_alloc(NULL);//申请内存从缓冲池进行申请(Allocates a buffer block.)
              block = (mem_block_t*) buf_block->frame;// 每个页在缓冲池中对应的数据结构。
                }
        UNIV_INTERN mem_pool_t*    mem_comm_pool    = NULL;
    以上是mem_block_t是从内存池进行分配的。

2.InnoDB内存池的相关结构,该内存池主要是InnoDB引擎内存数据结构对象(数据字典以及自适应哈希),并非是InnoDB内存页哦。
该内存池是用于小块内存的分配。内存池内存主要为如下结构分配内存:
  (1)数据字典。
  (2)自适应哈希索引。
  "Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures."


3.该内存池调用的函数关系如下:
   (1)innobase_init(void    *p)[ha_innodb.cc]->innobase_start_or_create_for_mysql(void)
        /*********************************************************************//**
        Opens an InnoDB database.
        @return    0 on success, error code on failure */
       static int innobase_init

   (2)innobase_start_or_create_for_mysql(void)[srv0start.cc]->srv_boot();
        /********************************************************************
        Starts InnoDB and creates a new database if database files
        are not found and the user wants.
       @return    DB_SUCCESS or error code */
     UNIV_INTERN dberr_t innobase_start_or_create_for_mysql(void)

   (3)srv_boot(void)[srv0srv.cc]->srv_general_init()
        /*********************************************************************//**
        Boots the InnoDB server. */
        UNIV_INTERN    void srv_boot(void)

   (4)srv_general_init(void)[srv0srv.cc]->mem_init(srv_mem_pool_size);
        /*********************************************************************//**
        Initializes the synchronization primitives, memory system, and the thread
        local storage. */
        UNIV_INTERN void srv_general_init(void)

        srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
         srv_mem_pool_size定义在ha_innodb.cc中

   (5)    mem_init(ulint    size)[memdbg.cc]->mem_pool_create(size);
        /******************************************************************//**
        Initializes the memory system. */

   (6) mem_pool_create(ulint    size)[mem0pool.cc]
        /********************************************************************//**
        Creates a memory pool.
        @return    memory pool */
  从以上的关系来讲,该内存池就是管理额外缓冲池的,而额外缓冲池是管理数据结构是用的。

(1)如下为内存堆得相关数据结构:

/** The info structure stored at the beginning of a heap block */
struct mem_block_info_t {
    ulint    magic_n;/* magic number for debugging */
#ifdef UNIV_DEBUG
    char    file_name[8];/* file name where the mem heap was created */
    ulint    line;    /*!< line number where the mem heap was created */
#endif /* UNIV_DEBUG */
    UT_LIST_BASE_NODE_T(mem_block_t) base; /* In the first block in the
            the list this is the base node of the list of blocks;
            in subsequent blocks this is undefined */
    UT_LIST_NODE_T(mem_block_t) list; /* This contains pointers to next
            and prev in the list. The first block allocated
            to the heap is also the first block in this list,
            though it also contains the base node of the list. */
    ulint    len;    /*!< physical length of this block in bytes */
    ulint    total_size; /*!< physical length in bytes of all blocks
            in the heap. This is defined only in the base
            node and is set to ULINT_UNDEFINED in others. */
    ulint    type;    /*!< type of heap: MEM_HEAP_DYNAMIC, or
            MEM_HEAP_BUF possibly ORed to MEM_HEAP_BTR_SEARCH */
    ulint    free;    /*!< offset in bytes of the first free position for
            user data in the block */
    ulint    start;    /*!< the value of the struct field ‘free‘ at the
            creation of the block */
#ifndef UNIV_HOTBACKUP
    void*    free_block;
            /* if the MEM_HEAP_BTR_SEARCH bit is set in type,
            and this is the heap root, this can contain an
            allocated buffer frame, which can be appended as a
            free block to the heap, if we need more space;
            otherwise, this is NULL */
    void*    buf_block;
            /* if this block has been allocated from the buffer
            pool, this contains the buf_block_t handle;
            otherwise, this is NULL */
#endif /* !UNIV_HOTBACKUP */
#ifdef MEM_PERIODIC_CHECK
    UT_LIST_NODE_T(mem_block_t) mem_block_list;
            /* List of all mem blocks allocated; protected
            by the mem_comm_pool mutex */
#endif
};

(2)如下为内存池相关的结构或者函数的定义
#define UT_LIST_BASE_NODE_T(TYPE)                    struct {                                    int   count;  /*!< count of nodes in list */                TYPE *  start;  /*!< pointer to list start, NULL if empty */        TYPE *  end;    /*!< pointer to list end, NULL if empty */    }

#define UT_LIST_NODE_T(TYPE)                        struct {                                    TYPE*    prev;    /*!< pointer to the previous node,                    NULL if start of list */                TYPE*    next;    /*!< pointer to next node, NULL if end of list */}
/** Memory area header */
struct mem_area_t{
    ulint        size_and_free;    /*!< memory area size is obtained by
                    anding with ~MEM_AREA_FREE; area in
                    a free list if ANDing with
                    MEM_AREA_FREE results in nonzero */
    UT_LIST_NODE_T(mem_area_t)
            free_list;    /*!< free list node */
};
/** Data structure for a memory pool. The space is allocated using the buddy
algorithm, where free list i contains areas of size 2 to power i. */
struct mem_pool_t{
    byte*        buf;        /*!< memory pool */
    ulint        size;        /*!< memory common pool size */
    ulint        reserved;    /*!< amount of currently allocated
                    memory */
    ib_mutex_t        mutex;        /*!< mutex protecting this struct */
    UT_LIST_BASE_NODE_T(mem_area_t)
            free_list[64];    /*!< lists of free memory areas: an
                    area is put to the list whose number
                    is the 2-logarithm of the area size */
};

/********************************************************************//**
Creates a memory pool.
@return    memory pool */
UNIV_INTERN mem_pool_t* mem_pool_create(
/*============*/
    ulint    size)    /*!< in: pool size in bytes */
{
    mem_pool_t*    pool;
    mem_area_t*    area;
    ulint        i;
    ulint        used;

    pool = static_cast<mem_pool_t*>(ut_malloc(sizeof(mem_pool_t))); //内存池的信息

    pool->buf = static_cast<byte*>(ut_malloc_low(size, TRUE)); //申请大小为size的内存池,该Size是由innodb_additional_mem_pool_size提供
    pool->size = size;

    mutex_create(mem_pool_mutex_key, &pool->mutex, SYNC_MEM_POOL); //添加互斥量

    /* Initialize the free lists */

    for (i = 0; i < 64; i++) {

        UT_LIST_INIT(pool->free_list[i]);
    }

    used = 0;

    while (size - used >= MEM_AREA_MIN_SIZE) {

        i = ut_2_log(size - used); //ut_2_log(N):X=0;for(){N=N/2;if(N==0)break;}

        if (ut_2_exp(i) > size - used) { //ut_2_exp是2的i次幂

            /* ut_2_log rounds upward */

            i--;
        }

        area = (mem_area_t*)(pool->buf + used);

        mem_area_set_size(area, ut_2_exp(i));
        mem_area_set_free(area, TRUE);
        UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area,
                  ut_2_exp(i) - MEM_AREA_EXTRA_SIZE);

        UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area);

        used = used + ut_2_exp(i);
    }

    ut_ad(size >= used);

    pool->reserved = 0;

    return(pool);
}
时间: 2024-08-13 21:11:27

innodb内存管理的相关文章

MySQL系列:innodb引擎分析之内存管理

在innodb中实现了自己的内存池系统和内存堆分配系统,在innodb的内存管理系统中,大致分为三个部分:基础的内存块分配管理.内存伙伴分配器和内存堆分配器.innodb定义和实现内存池的主要目的是提供内存的使用率和效率,防止内存碎片和内存分配跟踪和调试.我们先来看看他们的关系和结构. 以下是它的关系结构图: 上图中的: ut_mem_block块是基础内存管理 Buddy allocator是内存伙伴分配器 mem_heap是内存堆分配器 1.基础内存管理 innodb中的内存分配和内存释放是

MySQL系列:innodb源代码分析之内存管理

在innodb中实现了自己的内存池系统和内存堆分配系统,在innodb的内存管理系统中,大致分为三个部分:基础的内存块分配管理.内存伙伴分配器和内存堆分配器.innodb定义和实现内存池的主要目的是提供内存的使用率和效率,防止内存碎片和内存分配跟踪和调试.我们先来看看他们的关系和结构. 下面是它的关系结构图: 上图中的: ut_mem_block块是基础内存管理 Buddy allocator是内存伙伴分配器 mem_heap是内存堆分配器 1.基础内存管理 innodb中的内存分配和内存释放是

MySQL——innodb日志管理

innodb日志管理机制: 1.innodb存储引擎是支持事务ACID特性的,这个理论基本就是一个关系型数据库相关的数据恢复原形设计,包括日志.回滚.redo.并发控制.buffer pool等管理方面,内容非常全面: 2.innodb的buffer pool主要用来存储访问过的数据页面,他就是一块连续的内存,通过一定的算法可以使这块内存得到有效的管理,它是数据库系统中拥有最大块内存的系统模块. innodb存储引擎中数据的访问是按照页(也可以叫块,默认为16KB)的方式从数据库文件读取到buf

linux内存管理

一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程序可调用它.假如机器中有数个进程运行相同的一个程序,那么它们就可以使用同一个代码段.     2) 数据段:存放已初始化的全局变量.静态变量(包括全局和局部的).常量.static全局变量和static函数只能在当前文件中被调用.     3) 未初始化数据区(uninitializeddata s

Block内存管理实例分析

在ios开发中,相信说道block大家都不陌生,内存管理问题也是开发者最头疼的问题,网上很多讲block的博客,但大都是理论性多点,今天结合一些实例来讲解下. 存储域 首先和大家聊聊block的存储域,根据block在内存中的位置,block被分为三种类型: NSGlobalBlock NSStackBlock NSMallocBlock 从字面意思上大家也可以看出来 NSGlobalBlock是位于全局区的block,它是设置在程序的数据区域(.data区)中. NSStackBlock是位于

Obstack是C标准库里面对内存管理的GNU扩展

Obstack介绍 Obstack初始化 在Obstack中申请对象 释放对象 申请growing object 获取Obstack状态 数据对齐 以下是来自wiki对obstack的介绍: Obstack是C标准库里面对内存管理的GNU扩展(实际上就是GNU C library了).Obstack===Object stack.没错,Obstack就是一个栈,栈里面的元素是对象object(不是面向对象的对象哦,这里的对象单指数据元素).这些数据是动态的,也就是使用的是动态内存.这种内存管理技

OC内存管理

OC内存管理 一.基本原理 (一)为什么要进行内存管理. 由于移动设备的内存极其有限,所以每个APP所占的内存也是有限制的,当app所占用的内存较多时,系统就会发出内存警告,这时需要回收一些不需要再继续使用的内存空间,比如回收一些不再使用的对象和变量等. 管理范围:任何继承NSObject的对象,对其他的基本数据类型无效. 本质原因是因为对象和其他数据类型在系统中的存储空间不一样,其它局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时这个代码块中涉及的所有局部变量会被回收,指向对象的指针也

39-oc集合中对象的内存管理

集合中对象的内存管理 集合的内存管理原则是什么 当把一个对象添加到集合中时,这个对象会做了一次retain操作,计数器会+1 当一个集合被销毁时,会对集合里面的所有对象做一次release操作,计数器会-1 当一个对象从集合中移除时,会对这个对象做一次release操作,计数器会-1 集合方法的普遍规律是什么 如果方法名是add\insert开头,那么被添加的对象,计数器会+1 如果方法名是remove\delete开头,那么被移除的对象,计数器-1

iOS基础 ----- 内存管理

Objective-C 的内存管理方式有引用计数机制,垃圾回收机制,自动释放池.有alloc,就有释放.iOS应?程序出现Crash(闪退),90%的原因是因为内存问 题.在?个拥有数?个甚?是上百个类的?程?,查找内存问 题极其困难,学会内存管理,能帮我们减少出错的?率.内存问题体现在两个??:内存溢出.野指针异常. 引用计数器 在Xcode4.2及之后的版本中由于引入了ARC(Automatic Reference Counting)机制,程序编译时Xcode可以自动给你的代码添加内存释放代