Innodb Log写入方式分析

作者/译者:王佳隆 来源: http://www.mysqlsupport.cn/ 联系方式:enjoylonely#live.cn  转载请注:译者和出处,并且不能用于商业用途,违者必究.

原文URL:http://www.mysqlperformanceblog.com/2010/07/16/analyzing-the-distribution-of-innodb-log-file-writes/

    最近我分析了一下Innodb是如何写多个日志的。我这里有个流量比较高的MySQL系统,使用的是Percona XtraDB存储引擎,

我使用strace命令分别跟踪了innodb如何去日志文件的。通常来说,innodb是以512bytes的大小来写入日志的。

关于这个可以参考:Mark Callaghan explained this and some of its performance implications 。那么innodb什么时候情况下会以大于512bytes者小于512bytes的请求写到日志里呢?

首先,我通过lsof命令找出日志的文件描述符(handle).

# lsof -p $(pidof mysqld) | grep ib_log
mysqld  29772 mysql    8uW  REG                8,2   268435456   7143989 /var/lib/mysql/ib_logfile0
mysqld  29772 mysql    9uW  REG                8,2   268435456   7143993 /var/lib/mysql/ib_logfile1

我们可以看到2个日志的handle为8和9,现在我们需要捕获innodb是如何写这2个日志的相关信息。Innodb轮循写日志就是通过这个文件描述符.

The following grabs the write sizes out of 100k calls to pwrite() and aggregates them:

# strace -f -p $(pidof mysqld) -e pwrite -s1 -xx 2>&1 \

   | grep ‘pwrite([89],’ |head -n 100000 \

   | awk ‘{writes[$5]++}END{for(w in writes){print w, ” “, writes[w]}}’

本来我可以写一个更好的脚本来捕获信息,但是下面的信息对我来说已经足够了。

bytes        count
512           44067
1024         30740
1536         15221
2048         7094
2560         1810
3072         570
3584         219
4096         112
4608         39
5120         23
5632         16
6144         15
6656         5
7168         3
7680         8
8192         2
8704         2
9216         1
9728         2
10240       1
10752       2
11264       1
11776       1
14848       1
15360       1
15872       2
16384       4
16896       4
17408       2
17920       2
18432       2
18944       8
19456       7
19968       4
20480       4
21504       1
22016       2
24064       1
40960       1

总的来说,大致有3/4是以512和1024字节写入的。那么这到底什么意思呢?这里有很多有趣的而且复杂的东西需要我们去研究。

 1. 我们可以看到,大部分的写入都小于4K。但是我们知道操作系统的page大小是4K的。如果要写入的page不在cache中,那么这个page最开始需要读出,然后再修改,最后再写回到磁盘。vadim曾经过做做一些测试,如果要性能最好,那么日志要在OS的cache中。

 2.这台MySQL的innodb_flush_log_at_trx_commit设置是2.这就说明每个事务都会有一个日志写入请求,这个和设置为1是一样的。但是如果设置成0,那么写入的方法就大不相同—这个时候写入请求会累计到一定程度,然后一起写入。

 3.那么如果说log buffer小于一个事务要写的日志大小怎么办?这是另外一个需要研究的主题了。目前我还不清楚。

4.从上面的信息来看,是否可以很容易知道log buffer大小应该给多少呢?最大的写入小于40K,这好像可以说明分配64K给log buffer就已经足够了。这是真的吗?我们需要去测试才可以知道。peter以前和我谈过这个问题,log buffer背后的机制其实是很复杂的,到底log buffer需要保留多少空间给写操作。这些都需要更深入的研究。但是有一点可以确认,即使最大的写入操作不是很大的情况下,如果log buffer设置太小,性能肯定是不好的,而且会造成而外的锁。这个问题或许我们同样需要去研究。

最后,研究innodb是如何写日志的很容易,但是事实上innodb redo log机制是很复杂的,有时候我们很难说去猜想应该是什么样的,而应该去更深入的研究才可以知道的更多。也许我们可以按照上面这种步骤去研究不同LOG buufer大小,不同的日志参数设置,以及不同的服务器负载的情况下innodb到底是如何来写入日志的。

参考地址:http://mysqlha.blogspot.com/2009/06/buffered-versus-direct-io-for-innodb.html