分类: Mysql/postgreSQL
2012-02-03 10:00:33
注意InnoDB的记录长度,控制Blob字段的数量
由于熊熊内测希望换64位MySQL DB。有点担心稳定问题,研究了半天kavin当年给的innodb db bug 记录。我们用的MySQL都是5.0。
090609 22:09:41InnoDB: Assertion failure in thread 696346 in file btr0cur.c line 3781
InnoDB: Failing assertion: copied_len == local_len + extern_len
InnoDB: We intentionally generate a memory trap.
后面又仔细看了robinfu和jackai的总结帖。 发现可能是由于InnoDB,Got error 139 from storage engine错误导致的。
又看了半天MySQL的innodb 的手册,发现对于Got error 139 from storage engine 错误,innodb有比较详细的解释。
http://dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html
http://dev.mysql.com/doc/refman/5.0/en/innodb-file-space.html
简单说就是一个记录(行)的长度不要超过的1半(默认大约8K),行的长度一般情况下就是字段数据长度综合,但数据字段中如果有BLOB(TEXT)。
BLOB(TEXT)的长度如果大于768字节,就会在这个页面上放一部分(768个字节)的数据,其他数据放到其他页面上,所以当BLOB字段的总数大约10,
且每个字段都大于768个字节时,总长度就会大于8000(准确可能是8192),就会出现Got error 139 from storage engine 错误,(注意这个错误只是修改失败,不会Crash)
但注意这个是充分条件。不是必要条件。充分必要条件就是数据记录长度大于8000,你要考虑你还有其他字段也要占用空间。
解决这个问题的最简单的方法就是减少blob的字段,同时老老实实的估计自己的行长度。(熊熊现在的BLOB字段5个。)
对于这个错误的最简单的规避方法还可以调整innodb_page_size(默认长度是16K)的长度。这样你可以容纳更多的BLOB字段了。但扩大可能会引发脏空间的问题。
当然你还可以不用innodb,但是innodb现在已经是用的最广泛的MYSQL引擎了,靠的是实力。
随便说一句,我看一个修改记录MYSQL3.23的某个版本就说过Innodb解决了一行8000的限制问题,怎么改着改着又改回去了。
但这个问题是否会引发innodb crash,我的观点和jackai类似,出现这个错误后的确出现了Crash,但是未必是这个错误导致的。从crash的断言附近的代码看,应该是出现了数据异常。我google半天发现一个比较类似的问题报告。(断言发发生的地方一样)
但是没有结论,MySQL的开发者认为可能是磁盘或者硬件异常导致的,或者说是出现故障后错误的修复导致的。由于无法了解当时场景和是否操作(有点怀疑我收到的错误信息是否正确),所以我也无从判断是否有这类可能。
另外的可能是在错误处理上没有回滚好。导致了某些数据的异常,但我无法重现。据说公司出现过多起这类事故。但MYSQL的开发者信誓旦旦No bug has ever been found in InnoDB that could explain the file corruption cases that have been reported from Linux in the past 5 years. (2006年)
看过新的版本5.0.85的版本感觉在这个代码附近也没有什么修正。
谢谢robinfu和jackai的总结。
BTW,看了一下最近的MySQL的发展,惊讶的发现google居然帮助了MySQL进行了很多修补。MySQL的5.4版本和Innodb新的plugin都是和Google帮助有关。
Google的境界和实力不服不行。