博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据库内核月报 - 2015 / 10-TokuDB · 捉虫动态 · CREATE DATABASE 导致crash问题
阅读量:6071 次
发布时间:2019-06-20

本文共 1691 字,大约阅读时间需要 5 分钟。

背景

TokuDB在启动的时候,会对datadir目录下的文件(和文件夹)进行遍历,根据规则找到所有的redo log文件,然后进行recover操作。

redo文件的命名规则是:log[index].toku[version],比如log000000000002.tokulog27。

问题

这个bug说起来有点“谜之”,因为它还跟编译器的版本有关。

如果使用gcc 4.8.2编译出一个TokuDB(加-O3编译参数),进行如下操作:

CREATE DATABASE log0002;

然后重启,整个TokuDB就可能凌乱了,出现如下crash信息:

storage/tokudb/ft-index/ft/logger/logfilemgr.cc:159 toku_logfilemgr_init: Assertion 'r==2' failed (errno=2)Backtrace: (Note: toku_do_assert=0x0xcd50d0)mysqld(_Z20toku_logfilemgr_initP15toku_logfilemgrPKcPm+0x26c)[0xc40cdc]mysqld(_Z30toku_logger_open_with_last_xidPKcP10tokuloggerm+0x51)[0xc10ba1]mysqld(_Z14tokuft_recover)

原因

先来看下TokuDB判断一个文件是否为redo log的代码:

static bool is_a_logfile_any_version (const char *name, uint64_t *number_result, uint32_t *version_of_log) {	bool rval = true;	uint64_t result;	int n;	int r;	uint32_t version;	r = sscanf(name, "log%" SCNu64 ".tokulog%" SCNu32 "%n", &result, &version, &n);	if (r!=2 || name[n]!='\0' || version <= TOKU_LOG_VERSION_1) {		//Version 1 does NOT append 'version' to end of '.tokulog'		version = TOKU_LOG_VERSION_1;		r = sscanf(name, "log%" SCNu64 ".tokulog%n", &result, &n);		if (r!=1 || name[n]!='\0') {			rval = false;		}	}	if (rval) {		*number_result  = result;		*version_of_log = version;	}	return rval;}

这段代码的逻辑很简单,调用sscanf函数获取相关参数, 高能区域为:

r = sscanf(name, "log%" SCNu64 ".tokulog%" SCNu32 "%n", &result, &version, &n);

如果name为log0002,调用完sscanf函数后,n和version的值是不确定的(因为函数内变量未被初始化),就可能导致函数 is_a_logfile_any_version 把log0002文件夹误认为是一个redo log。

toku_logfilemgr_init函数加载名称“log0002”时做二次校验,获取version值失败从而触发assert。

修复

大体思路是:

  1. 由于redo log不可能是文件夹,所以增加只对文件进行判断的逻辑,遇到文件夹直接跳过;
  2. is_a_logfile_any_version函数内变量进行初始化。

阿里云RDS TokuDB最新版本已经修复此问题,使用TokuDB的用户可以进行下小版本升级,以避免此问题影响业务。

转载地址:http://vnbgx.baihongyu.com/

你可能感兴趣的文章
while((ch = getchar()) != '\n')
查看>>
好程序员web前端分享JS检查浏览器类型和版本
查看>>
Linux 安装oracle内核参数
查看>>
Oracle DG 逻辑Standby数据同步性能优化
查看>>
exchange 2010 队列删除
查看>>
android实用测试方法之Monkey与MonkeyRunner
查看>>
「翻译」逐步替换Sass
查看>>
H5实现全屏与F11全屏
查看>>
处理excel表的列
查看>>
枸杞子也能控制脂肪肝
查看>>
Excuse me?这个前端面试在搞事!
查看>>
C#数据采集类
查看>>
quicksort
查看>>
检验函数运行时间
查看>>
【BZOJ2019】nim
查看>>
Oracle临时表空间满了的解决办法
查看>>
四部曲
查看>>
LINUX内核调试过程
查看>>
【HDOJ】3553 Just a String
查看>>
Java 集合深入理解(7):ArrayList
查看>>