在InnoDB中,bufferpool里面的dirtypage一方面可以加快数据处理速度,同时也会造成数据的不一致(RAMvsDISK)。本文介绍了dirtypage是如何产生,以及InnoDB如何利用redolog如何消除dirtypage产生的数据不一致。
当事务(Transaction)需要修改某条记录(row)时,InnoDB需要将该数据所在的page从disk读到bufferpool中,事务提交后,InnoDB修改page中的记录(row)。这时bufferpool中的page就已经和disk中的不一样了,我们称bufferpool中的page为dirtypage。Dirtypage等待flush到disk上。
dirtypage既然是在Bufferpool中,那么如果系统突然断电Dirtypage中的数据修改是否会丢失?这个担心是很有必要的,例如如果一个用户完成一个操作(数据库完成了一个事务,page已经在bufferpool中修改,但dirtypage尚未flush),这时系统断电,bufferpool数据全部消失。那么,这个用户完成的操作(导致的数据库修改)是否会丢失呢?答案是不会(innodb_flush_log_at_trx_commit=1)。这就是redolog要做的事情,在disk上记录更新。
redolog在每次事务commit的时候,就立刻将事务更改操作记录到redolog。所以即使bufferpool中的dirtypage在断电时丢失,InnoDB在启动时,仍然会根据redolog中的记录完成数据恢复。
redolog的另一个作用是,通过延迟dirtypage的flush最小化磁盘的randomwrites。(redolog会合并一段时间内TRX对某个page的修改)
正常情况下,dirtypage什么时候flush到disk上?
1).redolog是一个环(ring)结构,当redo空间占满时,将会将部分dirtypageflush到disk上,然后释放部分redolog。这种情况可以通过Innodb_log_wait(SHOWGLOBALSTATUS)观察,情况发生该计数器会自增一次。
2).当需要在Bufferpool分配一个page,但是已经满了,并且所有的page都是dirty的(否则可以释放不dirty的page),通常是不会发生的。这时候必须flushdirtypagestodisk。这种情况将会记录到Innodb_buffer_pool_wait_free中。一般地,可以可以通过启动参数innodb_max_dirty_pages_pct控制这种情况,当bufferpool中的dirtypage到达这个比例的时候,将会强制设定一个checkpoint,并把dirtypageflush到disk中。
3).检测到系统空闲的时候,会flush,每次64pages。
涉及的InnoDB配置参数:innodb_flush_log_at_trx_commit、innodb_max_dirty_pages_pct;状态参数:Innodb_log_wait、Innodb_buffer_pool_wait_free。
我的my.cnf文件是这样的
innodb_data_home_dir = /usr/local/mysql/var
innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = /usr/local/mysql/var
innodb_buffer_pool_size = 16M
innodb_additional_mem_pool_size = 2M
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50
结果启动的时候报错如下:
130904 16:26:00 [ERROR] /usr/local/mysql/libexec/mysqld: unknown variable 'innod
b_data_file_path=ibdata1:10M:autoextend'
130904 16:26:00 [ERROR] Aborting
130904 16:26:00 [Note] /usr/local/mysql/libexec/mysqld: Shutdown complete
130904 16:26:00 mysqld_safe mysqld from pid file /usr/local/mysql/var/test4.wolf
.org.pid ended
我查看得知
>show variables like 'have%';
如果 have_innodb = NO 的话,那确实是编译的时候innodb没有加载进去。
那么需要重新编译的时候 ./configure ... --with-plugins=innobase
唉唉唉唉,只有重新编译了
[root@test4 mysql-5.1.70]# ./configure --prefix=/usr/local/mysql --enable-assembler --datadir=/mysql/data --with-client-ldflags=-all-static--with-unix-socket-path=/tmp --with-charset=utf8 --enable-thread-safe-client --with-pthread --without-debug --with-big-tables --enable-community-features --enable-profiling --enable-local-infile --with-fast-mutexes --with-plugins=partition,federated,ndbcluster,innobase,csv,blackhole,myisam,innodb_plugin
[root@test4 mysql-5.1.70]# make && strip sql/mysqld && make install
如果你编译安装 的时候编译了innnodb但是还是出现这位洋的问题,那么就这么解决
解决如下:
/var/lib/mysql目录下,删除ibdata1、ib_logfile1、 ib_logfile0,然后重启MySql让其重建以上文件:
mysqladmin -uroot -p shutdown
sudo mysqld_safe &
搞定!