宋宝华: 数据库为什么有可能喜欢Linux AIO(异步I/O)?

回忆一下

我们都知道Linux的IO模型有阻塞、非阻塞、SIGIO、多路复用(select,epoll)、AIO(异步I/O)等。

数据库可能比较倾向于使用AIO。从时序上面来讲,AIO是用户应用发起IO请求io_submit()后,它就不需要去等待,让后台给它搞定读写。之后本线程或者其他线程就可以通过io_getevents()去同步I/O的结果。

这样的AIO有一个极大的好处在于,IO不会阻塞住CPU的行为,有利于充分利用硬件的资源,有利于让CPU、IO都parallel起来 。当然,同样的动作,似乎用epoll()、SIGIO也可以呈现出来。尤其是epoll(),几乎是C10K问题解决方案在Linux的代名词。epoll_wait()先等待IO请求的read、write可以发生,而后再根据返回的事件发起读写请求:

事件驱动模型libevent等,看起来是事件到来,callback被执行的Reactor模式:

但是其底层其实也是靠epoll()来实现,这个我们透过strace就可以看出。请见我的3分钟小电影:

大不一样

epoll()本质上其实还是先等待IO的读写可以发生,而后再以Linux常规read()、write() API去发起IO请求。而AIO则是不管三七二十一,直接发IO请求,但是并不等待这个请求的结束,让Linux后台自己去完成读写。我们来看一个典型的AIO编程案例:

它是通过io_submit()把IO请求发出去之后,它并不需要等IO的结束。后面用io_getevents()去同步。上面的代码中,io_getevents()的代码与io_submit()的代码摆在一起,但是其实它们并不需要一定是同一个线程。

AIO和传统epoll()的本质区别是,epoll()等方式,它只是一个事件获取机制,获取事件后,之后的read(), write()还是要走Linux的传统路线,经过Linux内核本身的各个层次(如page cache,IO调度等)。而AIO是骨子里面,自己就是一个IO的方式,最终没有经过传统的Linux read(),write()这种"all is file"的类VFS接口。Linux native的AIO本身call的函数,本身就是系统调用。strace执行AIO动作的进程得到的直接就是类似如下的结果:

strace ./aio....

...

io_setup(128, {3077799936}) = 0

io_submit(3077799936, 1, 0xbfa5e730) = 1

io_getevents(-1217167360, 1, 1, {...}NULL) = 1

在ARM Linux的系统调用表里也可以看出:

故而,AIO可以更多地把机会交给用户空间,让用户空间根据自身的IO特点来为自己量身定制IO的行为。AIO一般也直接结合DIO(direct IO)来使用,进一步绕开内核本身的IO调度和cache机制。

我中意你

那么AIO有什么可能的优势被数据库所青睐呢?

1. 透过AIO,可以屏蔽掉Linux内核底层的page cache。而制定application-level的cache机制。

我们都知道,Linux会针对每个文件对应的inode,创立一个address_space,并以Radix树来组织它的page cache命中情况,page的替换算法,整体是LRU,预测页面本身的活跃度。这个策略,固然非常符合局部性原理(Locality),但是不能针对用户程序本身的特征,进行用户级的cache。

2.透过AIO(尤其是结合DIO),可以一定程度上,进行用户级别的IO scheduling。采用AIO,用户可以控制发送给内核的IO请求,从而控制谁比谁更重要。内核固然有它的IO调度算法,但是它是比较general的。

3. 透过AIO,可以进行用户级别的read-ahead和write-behind控制。

我们都知道,Linux内核本身会根据用户的读请求,去预测后续的读,从而在后续的读还没有发起的情况下,就提前预读。详见:《宋宝华: 文件读写(BIO)波澜壮阔的一生》,但是这种预读的page,并不一定是上层应用想要的page。而内核的write-behind机制,也可能导致内核累积到很多dirty数据后,出现写磁盘的突发性洪泛。现在AIO机制,我们把这些都交给用户。

4. 透过AIO,不阻塞地在前台线程,直接dispatch IO请求,带来很好的

scalability。在InnoDB里面,可以透过 innodb_use_native_aio来配置使用同步的IO还是AIO,而且它有一番对比,值得细细地品读。同步IO的时候,query threads是将IO请求放入queue,由InnoDB后台线程的每个线程处理一个IO请求。而AIO的时候,query threads直接发IO请求。

With synchronous I/O, query threads queue I/O requests, and InnoDB background threads retrieve the queued requests one at a time, issuing a synchronous I/O call for each. When an I/O request is completed and the I/O call returns, the InnoDB background thread that is handling the request calls an I/O completion routine and returns to process the next request. The number of requests that can be processed in parallel is n, where n is the number of InnoDB background threads. The number of InnoDB background threads is controlled by innodb_read_io_threads and innodb_write_io_threads.

With native AIO, query threads dispatch I/O requests directly to the operating system, thereby removing the limit imposed by the number of background threads. InnoDB background threads wait for I/O events to signal completed requests. When a request is completed, a background thread calls an I/O completion routine and resumes waiting for I/O events.

参考阅读

https://dev.mysql.com/doc/refman/8.0/en/innodb-linux-native-aio.html

https://www.scylladb.com/2017/10/05/io-access-methods-scylla/

https://blog.pythian.com/importance-oracle-database-related-kernel-parameters-aio-max-nr-bonus-track/

本文分享自微信公众号 - Linux阅码场(LinuxDev)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-09-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏二狗的DBA之路

python操作数据库

下载地址:https://pypi.python.org/pypi/MySQL-python/1.2.5 安装到系统即可。

8010
来自专栏二狗的DBA之路

MySQL登录验证的抓包

http://blog.chinaunix.net/uid-9234131-id-5088292.html

11850
来自专栏二狗的DBA之路

Anemometer基于pt-query-digest将MySQL慢查询可视化

http://ourmysql.com/archives/1359?utm_source=tuicool&utm_medium=referral

14440
来自专栏二狗的DBA之路

MySQL索引原理及慢查询优化

出处:美团技术博客 链接:http://tech.meituan.com/mysql-index.html

15040
来自专栏二狗的DBA之路

MySQL备份时候排除指定的数据库

使用mysqldump命令备份时候,--all-databases 可以备份所有的数据库。 使用ignore-table 还可以排除制定的表。但是,mysqld...

12240
来自专栏二狗的DBA之路

MySQL innodb_table_stats表不存在的解决方法

虽然重启之后 , 数据库会自动创建一个 ibdata1 文件 , 但是上述系统表也是 innodb 引擎 , 所以不能访问了 .

7940
来自专栏万能青年的 Java 编程

MySQL Explain关键字

使用 EXPLAIN 关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的。分析你的查询语句或是表结构的性能瓶颈。

8020
来自专栏架构专题

架构秘笈:移花接木。使用mysql模拟redis

这年头,你看到的东西未必就是你认为的东西。一个mysql协议的后面,可能是tidb;一个linux机器后面,可能是一个精简的docker;你觉得xjjdog是个...

9910
来自专栏二狗的DBA之路

干货!MySQL 资源大全

shlomi-noach 发起维护的 MySQL 资源列表,内容覆盖:分析工具、备份、性能测试、配置、部署、GUI 等。

16040
来自专栏二狗的DBA之路

【转载】58到家MySQL军规升级版

(1)对数据库性能影响较大,互联网业务,能让站点层和服务层干的事情,不要交到数据库层

6530

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励