InnoDB主要数据结构及调用流程

时间:2022-01-12 14:49:15
InnoDB主要数据结构及调用流程
      InnoDB是MySQL中常用的数据引擎。本文将从源码级别对InnoDB重点数据结构和调用流程进行分析。

  1. 主要数据结构(buf0buf.h)
    • Buf_pool
      InnoDB主要数据结构及调用流程

      Buf_pool是整个buffer系统中核心数据结构,数据库中所有的操作都会在这缓冲层得到体现。我们可以在配置文件中(InnoDB_buffer_pool_size)指定该缓冲池的大小。
      Buffer pool中又包含了多层数据结构:为了实现对buffer_pool的在线大小调整,引入了chunk数据结构;

    • Chunk
      InnoDB主要数据结构及调用流程
      在chunk数据结构是更具体的内存缓存,主要包含控制内存块的block结构。
       Block
      InnoDB主要数据结构及调用流程
      Block主要的数据结构是page和frame,这两个结构是用来存储硬盘上的数据库page的。当硬盘存储未使用压缩时,数据会被读取到frame中;当使用压缩后,会存储到page.zip中。
      Page结构必须要放在该结构体的第一个位置,方便以后使用指针时可以方便的在page和block间进行转换。
      例如:(buf_page_t *) buf_block_t *p
      可以得到一个类型为buf_page的指针

    • Page
      InnoDB主要数据结构及调用流程

      Page结构主要是存储硬盘上的文件,通过space和offset唯一对应到硬盘上的数据库文件;io_fix指出该page的类型(读或写);Zip存储压缩过的page。

    • Buf_pool示意图
      InnoDB主要数据结构及调用流程
    • Io_threads
      在InnoDB内部,使用默认配置参数时,共有10个线程,其中:
      4个read线程,4个write线程,负责进行异步的读写操作。
      1个log write线程,负责将操作记录进日志文件
      1个srv_master线程,负责定时写数据到磁盘等工作。
      在InnoDB插件初始化时,会调用innobase_start_or_create_for_mysql,此函数将完成InnoDB存储引擎的初始化工作。创建io threads的部分在函数是
      os_thread_create(io_handler_thread, n + i, thread_ids + i)其中io_handler_thread是回调函数,主要是为每个后台线程分配任务
      for (i = 0;; i++) {
      fil_aio_wait(segment);

      mutex_enter(&ios_mutex);
      ios++;
      mutex_exit(&ios_mutex);
      }
      fil_aio_wait中起主要作用的是os_aio_simulated_handle,该函数根据线程在InnoDB中的编号进行模拟的异步IO设置。
      segment = os_aio_get_array_and_local_segment(&array, global_segment);

      Aio 与 sync aio
      在mysql诞生时,Linux上还未出现AIO机制,于是InnoDB自己实现了一套异步io的框架。
      关于Linux aio的介绍,AIO first entered the Linux kernel in 2.5 and is now a standard feature of 2.6 production kernels. http://www.ibm.com/developerworks/linux/library/l-async/

      最近Innobase在innodb plugin中实现了真正的AIO机制。http://blogs.innodb.com/wp/2010/04/innodb-performance-aio-linux/ 我们会在以后的时间来介绍他。

    • Arrays
      • os_aio_read_array //异步读
      • os_aio_write_array //异步写
      • os_aio_ibuf_array //insert bufer
      • os_aio_log_array //日志array
      • os_aio_sync_array //同步io array
        在InnoDB中引入了sync aio,目标是为了在代码级别上与aio的形式保持一致。

      InnoDB主要数据结构及调用流程

      为了实现InnoDB的异步IO所引入的数组,系统中一共存在五类数组:

      当出现IO请求时,异步机制会将此请求插入其中一个插槽(slot),并等待执行请求的信号;IO完毕,从该插槽中删除。

    • Segment
      在array中,segment被用作array的标识符,根据segment值可以得到array的种类。例如在默认的array数量下(4个read,4个write)3号表示read array
      InnoDB主要数据结构及调用流程

    • Slot
      InnoDB主要数据结构及调用流程

      存放异步读写请求的插槽。

  2. 调用流程
    InnoDB主要数据结构及调用流程

    在InnoDB中,为了提高响应速度,有时需要立即返回数据,此时采用同步的读机制;而另一些对速度要求不是很高的情况下,例如预读取,InnoDB会采用异步读的方式来加载数据到内存。而在开启double write buffer写数据的情况下,InnoDB会先将数据写一遍到硬盘上某一块称之为double write buffer的区域,然后再在将来某时写到磁盘上,此时会根据系统的当前负载、当前内存中脏的页数有不同的延迟。

    异步读写时等待请求:
    InnoDB主要数据结构及调用流程

    当缓存块/文件读写完毕时,发出信号:
    fil_io() -> os_aio()->
    os_aio_simulated_wake_handler_threads()->os_aio_simulated_wake_handler_thread->
    os_event_set()->pthread_cond_broadcast()