mysiam表坏了

好长时间没写blog了 ^!^
这周遇到myisam表坏了,习惯性的repair一把,就恢复了。虽然简单,这次出现场景不一样,这次是在主库load data过程中,备库的myisam表坏了。奇怪发现,主库表为innodb的,备库怎么是myisam,当时彻底受精了。历史遗留问题。

sql thread及io thread异常都停了,repair操作后,start slave就正常起来了。

max_data_length异常了

change buffering与bug

线上库的alert.log中出现如下错误信息:

120120 11:21:16 InnoDB: Assertion failure in thread 1133807936 in file ibuf0ibuf.c line 4233
InnoDB: Failing assertion: page_get_n_recs(page) > 1

尝试修改三个参数不同值来启动mysqld,修改成如下值时

innodb_purge_threads=0
innodb_change_buffering=changes
innodb_force_recovery=4

能够启动mysqld,但无法写操作:

root@test 02:45:26>insert into t values (2);
ERROR 1030 (HY000): Got error -1 from storage engine

类似bug如下:

http://bugs.mysql.com/bug.php?id=61104

暂时解决:

可以考虑切到备库,暂时停用change buffering特性

以上信息来自印风同学,这里想简单介绍一下change buffering是什么,到底有什么用?

change buffering是MySQL5.5加入的新特性,change buffering是insert buffer的加强,insert buffer只针对insert有效,change buffering对insert、delete、update(delete+insert)、purge都有效。当修改一个索引块(secondary index)时的数据时,索引块在buffter pool中不存在,修改信息就会被cache在change buffer中,当通过索引扫描把需要的索引块读取到buffer pool时,会和change buffer中修改信息合并,再择机写回disk。

目的还是为了减少随机IO带来性能损耗,说明白了:把随机IO尽量变成顺序IO。现在SSD盛行,在SSD上随机访问和顺序访问性能几乎差不多的情况下,change buffering特性不会带来多大的性能提升,但对于廉价的机械硬盘,这个参数还是能帮助提高性能的。

change buffering由参数innodb_change_buffering控制:

all:buffer inserts, delete-marking operations, and purges.
none:Do not buffer any operations.
inserts:Buffer insert operations.
deletes:Buffer delete-marking operations.
changes:Buffer both inserts and delete-marking.  
purges:Buffer the physical deletion operations that happen in the background.

这篇文章没什么新意,第一天上班,看到印风同学写得邮件,以前没太在意change buffering特性,今天结合文档学习一下,随意记录一下。
MySQL5.5目前用得还不多,所以遇到的bug还有限,大范围推广,还需要做更多测试。

参考:

http://dev.mysql.com/doc/refman/5.5/en/innodb-performance-change_buffering.html
http://blogs.innodb.com/wp/2010/09/mysql-5-5-innodb-change-buffering/

mysql checkpoint理解

在mysql的doc并没有深入介绍checkpoint,本文主要对网上两篇文章阅读加上自己的理解,描述一下transaction log(redo log)和checkpoint之间的关系。
Innodb实现了Fuzzy Checkpoint和Sharp Checkpoint的机制,但在事务日志中,采用了Fuzzy Checkpoint,那何为Fuzzy Checkpoint? Innodb每次取最老的modified page(last checkpoint)对应的LSN,确保此page位置的LSN之前page都已flush到redo log,当mysql crash后,mysql扫描redo log,从last checkpoint开始apply redo log到buffer pool,直到last checkpoint对应的LSN等于Log flushed up to对应的LSN,mysql认为恢复完成。

查看redo log和checkpoint信息:

root@(none) 11:37:27>show engine innodb status \G;

 

 

 

Innodb的checkpoint和redo log有哪些紧密关系?
有几上名词需要解释一下:

Ckp age(动态移动):最老的dirty page还没有flush到数据文件,即没有做last checkpoint的范围
Buf age(动态移动):modified page information没有写到log中,但已在log buffer
Buf async(固定点):日志空间大小的7/8,当buf age移动到Buf async点时,强制把没有写到log中的modified page information开始写入到log中,不阻塞事务
Buf sync(固定点): 日志空间大小的15/16,当写入很大的,buf age移动非常快,一下子到buf sync的点,阻塞事务,强制把modified page information开始写入到log中。如果不阻塞事务,未做last checkpoint的redo log存在覆盖危险
Ckp async(固定点): 日志空间大小的31/32,当ckp age到达ckp async,强制做last checkpoint,不阻塞事务
Ckp sync(固定点):日志空间大小,当ckp age到达ckp sync,强制做last checkpoint,阻塞事务,存在redo log覆盖的危险

接下分析4种情况
1、 如果buf age在buf async和buf sync之间
2、 如果buf age在buf sync之后(当然这种情况是不存在,mysql有保护机制)
3、 如果ckp age在ckp async和ckp sync之间(这种情况是不存在)
4、 如果ckp age在ckp sync之后(这种情况是不存在)

第一种情况:

当写入量巨大时,buf age移动到buf async和buf sync之间,触发写出到log中,mysql把尽量多的log写出,如果写入量减慢,buf age又移回到“图一”状态。如果写入量大于flush log的速度,buf age最终会和buf sync重叠,这时所有的事务都被阻塞,强制将2*(Buf age-Buf async)的脏页刷盘,这时IO会比较繁忙。

第二种情况:

当然这种情况是不可能出现,因为如果出现,redo log存在覆盖的可能,数据就会丢失。buf age会越过log size,buf age的大小可能就超过log size,如果要刷buf age,那么整个log size都不够容纳所有的buf age。

第三种和第四种情况不存在分析:

ckp age始终位于buf age的后面(左边),因为ckp age是last checkpoint点,总是追赶buf age(将尽可能多的modified page flush到磁盘),所以buf age肯定是先到达到buf sync。

疑问:ckp async及ckp sync存在意义?

BTW:上周听了褚霸关于OS及mysql分享,收益不少,讲到page cache时候,也提到page cache也存在high water及low water,当dirty page触到low water时,os是开始flush dirty page到磁盘,到high water时,会阻塞一切动作,os会疯狂的flush dirty page,磁盘会很忙,存在IO Storm,如果来避免?就想褚霸说的,innodb其实就是操作系统,只是业务场景不同。Percona的Vadim Tkachenko提出增加类似mid water的点,详细参考(http://www.mysqlperformanceblog.com/2011/04/04/innodb-flushing-theory-and-solutions/)

本文参考:

http://blog.csdn.net/yah99_wolf/article/category/539408