现在的位置: 首页 > 综合 > 正文

innodb double buffer

2013年02月08日 ⁄ 综合 ⁄ 共 2748字 ⁄ 字号 评论关闭

原文是percona的mysql performance blog上面的:

http://www.mysqlperformanceblog.com/2006/08/04/innodb-double-write/

 

doublewrite:
It means Innodb will write data twice when it performs table space writes – writes to log files are done only once.

当innodb进行tablespace的写操作时,会写两次。而进行redo log file的写操作时,只写一次。

 

innodb的tablespace中有一个double write buffer。double write
buffer不同于其他的buffer是在内存中的,它是在inndob的公共tablespace ibdata文件中。double
write可通过设置参数:innodb_doublewrite=0来禁用double write buffer。

 

很想知道double write的大小,所以看了一下源代码,找到了一下的函数:

mysql-5.1.41/storage/innodb_plugin/trx/trx0sys.c:164

/****************************************************************//**
Creates or initialializes the doublewrite buffer at a database start. */
static
void
trx_doublewrite_init(
/*=================*/
    byte*    doublewrite)    /*!< in: pointer to the doublewrite buf
                header on trx sys page */
{
    trx_doublewrite = mem_alloc(sizeof(trx_doublewrite_t));

    /* Since we now start to use the doublewrite buffer, no need to call
    fsync() after every write to a data file */
#ifdef UNIV_DO_FLUSH
    os_do_not_call_flush_at_each_write = TRUE;
#endif /* UNIV_DO_FLUSH */

    mutex_create(&trx_doublewrite->mutex, SYNC_DOUBLEWRITE);

    trx_doublewrite->first_free = 0;

    trx_doublewrite->block1 = mach_read_from_4(
        doublewrite + TRX_SYS_DOUBLEWRITE_BLOCK1);
    trx_doublewrite->block2 = mach_read_from_4(
        doublewrite + TRX_SYS_DOUBLEWRITE_BLOCK2);
    trx_doublewrite->write_buf_unaligned = ut_malloc(
        (1 + 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE);

    trx_doublewrite->write_buf = ut_align(
        trx_doublewrite->write_buf_unaligned, UNIV_PAGE_SIZE);
    trx_doublewrite->buf_block_arr = mem_alloc(
        2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * sizeof(void*));
}

 

其中,TRX_SYS_DOUBLEWRITE_BLOCK_SIZE =
64,所以初始化时的大小应该是129个page。

 

1. 为什么需要double write?

目的是为了保证出现部分写失效(partial page write)--即数据页写到一半时就出现故障--时的数据安全性。

一般情况只需要用innodb的redo log就可以保证其ACID的特性了。为什么出现partial page write 的时候,recovery不能正常进行呢?

 

原因在于innodb的redo log的内容格式:

Innodb并不在日志中记录整个数据页,而是使用一种称之为“physiological”日志的技术,即日志项中只包含页号、对数据进行的操作(如更新一行记录)和日志序列号等信息。

 

redo log这样写的优点:

能够减少写入到日志的数据量。

缺点:

必须要求数据文件内的数据页内部的一致性。

 

It does not matter which page version it is – it could be “current”
version in which case Innodb will skip page upate operation or “former”
in which case Innodb will perform update. If page is inconsistent
recovery can’t proceed.

 

2. double write的工作原理:

你可以将doublewrite看作是在Innodb表空间内部分配的一个短期的日志文件,这一日志文件包含100个数据页。

Innodb在写出缓冲区中
的数据页时采用的是一次写多个页的方式,这样多个页就可以先顺序写入到doublewrite缓冲区并调用fsync()保证这些数据被写出到磁盘。

然后
数据页才被定出到它们实际的存储位置并再次调用fsync()。

故障恢复时Innodb检查doublewrite缓冲区与数据页原存储位置的内容,若数据页在doublewrite缓冲区中处于不一致状态将被简单的丢弃,若在原存储位置中不一致则从doublewrite缓冲区中还原。

 

检查double write和tablespace中的数据是否一致:

mysql-5.1.41/storage/innodb_plugin/trx/trx0sys.c:411

trx_sys_doublewrite_init_or_restore_pages

判断double write和tablespace中的数据page是否coruppted,通过checksum来判断的:

mysql-5.1.41/storage/innodb_plugin/buf/buf0buf.c:295

buf_page_is_corrupted

 

 

 

 

 

 

抱歉!评论已关闭.