I/O处理过程
对于系统而言,磁盘I/O通常会成为一个瓶颈,尤其是对于数据库而言。数据从磁盘读取到内存,存到CPU缓存和寄存器,然后进行处理,最后写会磁盘,如下图:
可看到IO操作分成了四个层面:
1)文件系统缓存:处理数据必须先从磁盘读到缓存,读取的时候不光把当前磁盘地址的数据,而是把相邻的数据也都读取到内存缓冲区内,每一次读取的数据称为一页(page、一般为4k或8k),然后修改,然后刷回磁盘。缓存的刷新涉及到两个参数:vm.dirty_background_ratio、vm.dirty_ratio。
2)block layer:该层就涉及到 IO调度算法,IO调度算法在mysql服务器是一个很重要的调优手段。系统中所有进程申请的IO操作,全部在这里进行排队,等待调度,然后写回磁盘。调度算法有四种:
1> Anticipatory: 适用于个人PC,单磁盘系统;
2> CFQ(Complete Fair Queuing):默认的IO调度算法,完全公平的排队调度算法。每一个进程的IO请求会安排进一个专门的IO队列,然后按照进程组来公平的调度IO,也就是每一个进程组之间按照公平的方式来调度IO。显然他适合多用户的系统,但是极为不适合作为数据库系统的IO调度算法,因为显而易见,数据库系统中,数据库进程肯定是IO最多的一个进程组,然后它却只能获得和其它进程一样多的IO调度机会。所以显然这是极为不合理的。数据库系统绝对不要使用该调度算法。
3> Deadline: 按照截止期限来循环在各个IO队列中进行调度,所以它提供了一个近实时的IO系统,并且磁盘throughput也很好,也不会造成starvation.一般mysql系统建议采用该调度算法。
4> NOOP: 简单的FIFO队列进行调度,No operation的意思是,它没有进行额外的将临近的IO进行合并的操作,所以它对CPU的使用极少。该调度算法特别适合于SSD。因为SSD在对待顺序IO和随机IO没有什么区别。所以它不需要对临近的IO进行合并。避免了合并操作对CPU的使用。
所以一般而言,对于mysql的系统,如果是SSD,那么应该使用NOOP调度算法,如果是磁盘,就应该使用Deadline调度算法。
查看与修改IO调度算法:
临时修改:
[root@localhost ~]# cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]
[root@localhost ~]# echo noop > /sys/block/sda/queue/scheduler
[root@localhost ~]# cat /sys/block/sda/queue/scheduler
[noop] anticipatory deadline cfq
永久修改:
vi /boot/grub/menu.lst
更改到如下内容:
kernel /boot/vmlinuz-2.6.18-8.el5 ro root=LABEL=/ elevator=deadline rhgb quiet
重启之后,查看调度方法:
cat /sys/block/sda/queue/scheduler
noop anticipatory [deadline] cfq
3)磁盘驱动层:对于顺序读系统而言,很容易在磁盘接口层的带宽上成为瓶颈所在;
4)磁盘:对于随机读多的系统而言,磁盘很容易成为瓶颈所在,一般的优化就是使用RAID或者换SSD;
影响磁盘I/O性能因素
首先,要知道影响磁盘I/O性能的因素,就得知道磁盘I/O请求所花费的时间的流程,它是由寻道时间、旋转延迟和数据传输三部分构成。
- 寻道时间
Tseek是指将读写磁头移动至正确的磁道上所需要的时间。寻道时间越短,I/O操作越快,目前磁盘的平均寻道时间一般在3-15ms。 - 旋转延迟
Trotation是指盘片旋转将请求数据所在的扇区移动到读写磁盘下方所需要的时间。旋转延迟取决于磁盘转速,通常用磁盘旋转一周所需时间的1/2表示。比如:7200rpm的磁盘平均旋转延迟大约为60*1000/7200/2 = 4.17ms,而转速为15000rpm的磁盘其平均旋转延迟为2ms。 - 数据传输时间
Ttransfer是指完成传输所请求的数据所需要的时间,取决于数据传输率,其值等于数据大小除以数据传输率。目前IDE/ATA能达到133MB/s,SATA II可达到300MB/s的接口数据传输率,数据传输时间通常远小于前两部分消耗时间。简单计算时可忽略。