数据库做为存储系统,全部业务访问数据的操做都会转化为底层数据库系统的IO行为(缓存系统也能够当作是key-value的数据库),本文主要介绍访问mysql数据库的IO流程以及IO相关的参数。
一 MySQL 的文件
首先简单介绍一下MySQL的数据文件,MySQL 数据库包含以下几种文件类型:
数据文件 (datafile) 存放表中的具体数据的文件。
数据字典 记录数据库中全部innodb表的信息。
重作日志 (redolog) 记录数据库变动记录的文件,用于系统异常crash(掉电)后的恢复操做,能够配置多个好比 ib_logfile0、 ib_logfile1,
回滚日志 (undolog) 也存在于mysql 的ibdata文件,用户记录事务的回滚操做。
归档日志 (binlog) 事务提交以后,记录到归档日志中。
中继日志 (relaylog) 从master 获取到slave 的中转日志文件,sql_thread 则会应用relay log
其余日志 slowlolg, errorlog, querylog
对于以上文件的IO访问顺序能够分为顺序访问 好比binlog ,redolog ,relay log是顺序读写,datafile,ibdata file是随机读写,这些IO访问的特色决定了在os 配置磁盘信息时候,如何考虑分区 ,好比顺序写能够的log 能够放到SAS 盘 ,随机读写的数据文件能够放到ssd 或者fio 高性能的存储。
二 数据访问流程
数据库访问分为两种类型, 一种是读操做,另一种是写操做。
1 读操做
create table t (
id int not null primary key ,
k1 int not null,
data varchar(50),
key ind_k1(k1)
) engine=innodb default charset=utf8;
以 select * from tab where k1=1 ;为例
图-1 读操做的 IO 流程
1 查看缓存中是否存在id,
2 若是有 则从内存中访问,不然要访问磁盘,
3 并将索引数据存入内存,利用索引来访问数据,
4 对于数据也会检查数据是否存在于内存,
5 若是没有则访问磁盘获取数据,读入内存。
6 返回结果给用户。
2 写操做
为了保证数据写入操做的安全性,数据库系统设置了 undo,redo 保护机制,避免由于os或者数据库系统异常致使的数据丢失或者不一致的异常状况发生。
以 insert into t values(1,1,'shuiyi');为例

图-2 写操做的 IO 流程
咱们假定数据在内存中,不考虑从磁盘中获取数据的情形。大体的写操做步骤:
1 先写undo log
2 在内存更新数据
3 记录变动到redo log,prepare
4 写入binlog
5 redo log 第二阶段,commit
6 返回给client
若是有slave
第4步以后 通过slave 服务线程 io_thread 写到从库的relay log ,再由sql thread 应用relay log 到从库中。
关于性能
写undo redo log ,binlog的过程当中都是顺序写,都会很快的完成,随机写操做,inset_buffer 功能
对于非汇集类索引的插入和更新操做(5.5 版本及以上支持Update/Delete/Purge等操做的buffer功能),不是每一次都直接插入到索引页中,而是先插入到内存中。具体作法是:若是该索引页在缓冲池中,直接插入;不然,先将其放入插入缓冲区中,再以必定的频率和索引页合并,就能够将同一个索引页中的多个插入合并到一个IO操做中,改随机写为顺序写,大大提升写性能。
关于数据安全,这是数据库写入的重点
1,2,3 过程失败 就是事务失败,由于此时还未写入磁盘,对磁盘中的数据无影响,返回事务失败给client,从库也不会受到影响。
4,5 过程失败的时候或者已经将写成功返回给客户,能够根据redo log 的记录来进行恢复,若是出现部分写失效 请参考《double write》
mysql的写redo log的第一个阶段会把全部须要作的操做作完,记录数据变动,第二阶段的工做比较简单 ,只作事务提交确认。若是写入binlog 成功,而第二阶段失败,mysql 启动时也会将事务进行重作,最终更新到磁盘中。
5.5 +的 smei sync
能够更好的保障主从的事务一致性。
三 文件访问方式
IO 访问的方式分为两种顺序读写和随机读写, 在mysql 的io过程当中能够以此来将数据库文件分类
顺序读写:
重作日志 ib_logfile*,binlog file
随机读写
innodb 表数据文件,ibdata文件。
根据系统的访问类型,对硬件作以下分类
读多 SSD+RAID
写多 FIO(flashcache)
容量密集 fio + flashcache
因为随机io会严重下降系统的性能,在当前的硬件水平下,能够考虑选择奖数据库服务器配置ssd/fusionio。
四 影响IO的参数和策略
影响mysql io 的参数有不少个,这里罗列几个重要的参数。
innodb_buffer_pool_size
该参数控制innodb 缓存大小,用于缓存应用访问的数据,推荐配置为系统可用内存的80%。
binlog_cache_size
该参数控制二进制日志缓冲大小,当事务尚未提交时,事务日志存放于cache,当遇到大事务cache不够用的时,mysql会把uncommitted的部分写入临时文件,等到committed的时候才会写入正式的持久化日志文件。
innodb_max_dirty_pages_pct
该参数能够直接控制Dirty Page在BP中所占的比率,当dirty page 达到了该参数的阈值,就会触发MySQL 系统刷新数据到磁盘
innodb_flush_log_at_trx_commit
该参数肯定日志文件什么时候write、flush。
为0,log buffer将每秒一次地写入log file中,而且log file的flush(刷到磁盘)操做同时进行.该模式下,在事务提交的时候,不会主动触发写入磁盘的操做。
为1,每次事务提交时MySQL都会把log buffer的数据写入log file,而且flush(刷到磁盘)中去.
为2,每次事务提交时MySQL都会把log buffer的数据写入log file.可是flush(刷到磁盘)操做并不会同时进行。该模式下,MySQL会每秒执行一次 flush(刷到磁盘)操做。
注意:
因为进程调度策略问题,这个“每秒执行一次 flush(刷到磁盘)操做”并非保证100%的“每秒”。
sync_binlog
sync_binlog 的默认值是0,像操做系统刷其余文件的机制同样,MySQL不会同步到磁盘中去而是依赖操做系统来刷新binary log。
当sync_binlog =N (N>0) ,MySQL 在每写 N次 二进制日志binary log时,会使用fdatasync()函数将它的写二进制日志binary log同步到磁盘中去。
innodb_flush_method
该参数控制日志或数据文件如何write、flush。可选的值为 fsync, o_dsync ,o_direct,littlesync,nosync
fdatasync 模式:写数据时,write这一步并不须要真正写到磁盘才算完成(可能写入到操做系统buffer中就会返回完成),真正完成是flush操做,buffer交给操做系统去flush,而且文件的元数据信息也都须要更新到磁盘。
O_DSYNC 模式:写日志操做是在write这步完成,而数据文件的写入是在flush这步经过fsync完成
O_DIRECT模式:数据文件的写入操做是直接从mysql innodb buffer到磁盘的,并不用经过操做系统的缓冲,而真正的完成也是在flush这步,日志仍是要通过OS缓冲
注意:关于mysql 和io相关的参数,并非一成不变的,须要根据自身业务系统和硬件系统作相应调整,系统上线以前,测试出一个最佳值。
五 小结
数据库的io是一个很复杂和细致的知识层面,涉及数据库层和OS层面的IO写入策略,也和硬件的配置有关,本文主要针对MySQL 层面作分析,可能分析的不够全面,请各位朋友指点。
六 参考文档