MySQL源码分析(4):InnoDB主要数据结构及调用流程

原文地址:http://software.intel.com/zh-cn/blogs/2010/09/01/mysql4innodb/

1.主要数据结构(buf0buf.h)
(1)Buf_pool

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第1张图片

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

Chunk

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第2张图片

在chunk数据结构是更具体的内存缓存,主要包含控制内存块的block结构;

Block

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第3张图片

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

Page

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第4张图片

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

Buf_pool示意图

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第5张图片

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的形式保持一致。

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第6张图片

为了实现InnoDB的异步IO所引入的数组,系统中一共存在五类数组:当出现IO请求时,异步机制会将此请求插入其中一个插槽(slot),并等待执行请求的信号;IO完毕,从该插槽中删除。

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

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第7张图片

Slot

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第8张图片

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

2.调用流程

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第9张图片

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

异步读写时等待请求:

MySQL源码分析(4):InnoDB主要数据结构及调用流程_第10张图片

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

你可能感兴趣的:(InnoDB)