思路话语

。Arlen:思想有多远你就能走多远...

InnoDB之Dirty Page、Redo log

 

在InnoDB中,buffer pool里面的dirty page一方面可以加快数据处理速度,同时也会造成数据的不一致(RAM vs DISK)。本文介绍了dirty page是如何产生,以及InnoDB如何利用redo log如何消除dirty page产生的数据不一致。

  1. 当事务(Transaction)需要修改某条记录(row)时,InnoDB需要将该数据所在的page从disk读到buffer pool中,事务提交后,InnoDB修改page中的记录(row)。这时buffer pool中的page就已经和disk中的不一样了,我们称buffer pool中的page为dirty page。Dirty page等待flush到disk上。

 

 

  1. dirty page既然是在Buffer pool中,那么如果系统突然断电Dirty page中的数据修改是否会丢失?这个担心是很有必要的,例如如果一个用户完成一个操作(数据库完成了一个事务,page已经在buffer pool中修改,但dirty page尚未flush),这时系统断电,buffer pool数据全部消失。那么,这个用户完成的操作(导致的数据库修改)是否会丢失呢?答案是不会(innodb_flush_log_at_trx_commit=1)。这就是redo log要做的事情,在disk上记录更新。
  2. redo log在每次事务commit的时候,就立刻将事务更改操作记录到redo log。所以即使buffer pool中的dirty page在断电时丢失,InnoDB在启动时,仍然会根据redo log中的记录完成数据恢复。
  3. redo log的另一个作用是,通过延迟dirty page的flush最小化磁盘的random writes。(redo log会合并一段时间内TRX对某个page的修改)
    1. 正常情况下,dirty page什么时候flush到disk上?
      1).redo log是一个环(ring)结构,当redo空间占满时,将会将部分dirty page flush到disk上,然后释放部分redo log。这种情况可以通过Innodb_log_wait(SHOW GLOBAL STATUS)观察,情况发生该计数器会自增一次。
      2).当需要在Buffer pool分配一个page,但是已经满了,并且所有的page都是dirty的(否则可以释放不dirty的page),通常是不会发生的。这时候必须flush dirty pages to disk。这种情况将会记录到Innodb_buffer_pool_wait_free中。一般地,可以可以通过启动参数innodb_max_dirty_pages_pct控制这种情况,当buffer pool中的dirty page到达这个比例的时候,将会强制设定一个checkpoint,并把dirty page flush到disk中。
      3).检测到系统空闲的时候,会flush,每次64 pages。
    2. 涉及的InnoDB配置参数:innodb_flush_log_at_trx_commit、innodb_max_dirty_pages_pct;状态参数:Innodb_log_wait、Innodb_buffer_pool_wait_free。

 

 

  • August 19th, 2009 at 11:15 | #1

    innodb_max_dirty_pages_pct 默认是90。你们设置的是多少?

  • 丁原
    August 20th, 2009 at 10:36 | #2

    写的有点深度,有点内涵,非常不错。

  • August 20th, 2009 at 14:54 | #3

    @binzhang:
    这个参数影响MySQL crash后InnoDB的恢复时间,所以参数值取决于业务对高可用性的要求。
    一般来说,我们都设置在50以下。

  • August 25th, 2009 at 00:25 | #4

    innodb_flush_log_at_trx_commit=1

    这样设置的话,每次commit一个事务的时候,redo log的每次插入都会操作磁盘。

    另外,redo log的内容是什么?如果是记录了所有事物的数据信息? 如果不是的话,它有根据什么可以在断电后续写未提交的page?

  • August 25th, 2009 at 17:45 | #5

    To 柱石:
    1).innodb_flush_log_at_trx_commit=1时,每次TRX commit,都会有redo log写入磁盘操作,这也是为什么InnoDB在高密度的写入操作时,比MyISAM慢的一个原因。“A linear write to the redo log is much faster than a seek and a write to the tablespace file”解释了为什么向磁盘写redo log而不直接写dirty page.

    2).关于redo log的具体数据格式,我并不清楚。如果关心的话,可以参考MySQL源代码中的mysql-*.*.*\storage\innobase\log\log0log.c文件,应该可以解开你的疑问。

    3).另外,可以肯定的是,redo log至少记录了TRX给数据带来的全部变化(无论数据是什么格式)。

  • August 27th, 2009 at 00:38 | #6

    在commit update的时候,如何保证被标记为dirty page的数据一定能被写进redo log呢?这里是不是有有个先后顺序?以我的理解是写日志成功后,才将buffer pool中updated的page标记为dirty,请求解答,谢谢。

  • February 10th, 2010 at 16:09 | #7

    redo log可能是利用磁盘缓存的机制来保障数据完整性的。“掉电时,磁头会借助惯性将缓存中的数据写入零磁道以外的暂存区域,等到下次启动时再将这些数据写入目的地”。但是当硬盘突然损坏时,我想大概还是会丢数据吧?

  • February 11th, 2010 at 21:40 | #8

    Eric:
    数据库的数据一致性和安全性是构建于存储安全性之上的。
    磁盘损坏的风险,需要通过RAID或者实时备份来解决。

  •  

     

    from:http://www.taobaodba.com/html/317_innodb-dirty-page-redo-log.html

    posted on 2010-06-30 18:48  Arlen  阅读(684)  评论(0编辑  收藏  举报

    导航