OceanBase0.4⾃举时库表创建过程
OceanBase 0.4 ⾃举时库表创建过程
传说,在OceanBase 0.4之前,表结构定义,包括系统内部元数据表,都从Schema⽂件中读取。0.4版本之后,通过SQL语句创建表结构(、)。
在开源的OceanBase 0.4版本(OB唯⼀开源版本)的RootServer代码中,是可以看到从⽂件中读取Schema配置的代码段,在: ()
else if (!local_schema_manager_->parse_from_file(config_.schema_filename, config))
{
TBSYS_LOG(ERROR, "parse schema error chema file is %s ", config_.schema_filename.str());
res = false;
}
其中,config_.schema_filename的默认值是,但,这个⽂件安装以后的内容很简单(源码构建时由src/r
ootserver/schema.ini拷贝⾄${prefix}/etc/schema.ini):
[app_name]
name=obtest        # edit the app name when you deploy OceanBase for the first time
max_table_id=2000    # do not edit
说明,从0.4版本开始,⾄少应⽤的库表Schema结构定义不再从配置⽂件中读取,⽽是通过SQL来定义。
Schema配置⽂件格式
通过⼀个⽰例来⼤致了解Schema配置⽂件格式:
[app_name]
name=collect
max_table_id=1003
[collect_item_id]
table_id=1001
table_type=2
column_info=1,16,item_name,varchar,20
column_info=1,17,new_price,int
rowkey=item_name
rowkey_max_length=9
max_column_id=17
[collect_info]
table_id=1002
table_type=2
colume_info=1,16,uid,int
column_info=1,17,item_name,varchar,20
column_info=1,18,item_price,int
column_info=1,19,collect_time,create_time
rowkey=uid,item_name
join=[item_name$item_name]%collect_item_id:item_name$item_name,item_price$new_price
rowkey_max_length=17
max_column_id=19
应⽤的信息
[app_name]
name=collect
max_table_id=1003
应⽤的信息都写在 app_name 这个section 中. ⽬前主要有两个配置项:
name ⽤来配置应⽤的名称, 是⼀个长度不超过128位的字符串.
max_table_id ⽤来记录当前已经使⽤的最⼤的table_id.
在OceanBase中, 每个表都由table_id唯⼀标识, 且table_id不可以被重复使⽤. max_table_id 这个配置项, 主要是为了⽅便 schema ⽣成程序记录已经使⽤过的table_id.
代码⼊⼝:
表的信息
[collect_info]
table_id=1002
table_type=2
...
rowkey=uid,item_name
join=rowkey[8,16]%collect_item_id:item_name$item_name,item_price$new_price
rowkey_max_length=17
max_column_id=19
...
每张表的信息都存放在以表名命名的section中。
table_id
配置了这张表在OceanBase系统中的唯⼀id,在OceanBase系统中, id的取值范围是0-65535.系统会保留0-1000的table_id供系统⾃⾝使⽤.
table_type
配置表是内存表还是磁盘表,取值为 1 的时候, 表⽰静态部分放到磁盘上, 为2的时候, 表⽰全部数据放到内存中.
max_column_id
配置本表中已经使⽤过的最⼤的列id, 由schema ⽣成程序维护并使⽤, 防⽌对列id的重⽤.
compress_func_name
可选项, 配置这个表在存储时使⽤的压缩算法名字.
block_size 可选项
配置表在存储成sstable时,采⽤的block⼤⼩.
use_bloomfilter 可选项
配置表是否使⽤布隆过滤器, ⾮零值为使⽤.
rowkey_max_length
配置表中主键的最⼤长度.
rowkey_split
配置表数据拆分是根据表主键值前多少位分布,把数据存储到多个tablet上存储。这个值告诉ChunkSe
rver, 在分拆数据到不同tablet 时哪些数据是不应该被分开的, ⽐如, 当这个值为9的时候, 表⽰主键前9个字节完全相同的记录放置到同⼀个tablet中.
在Schema配置⽂件读取程序源码,已将属性rowkey_max_length及rowkey_split相关代码注解掉,但做为表属性还是存在的,在后⾯内部元数据表的属性配置中可以看到在继续使⽤
代码⼊⼝:
列的定义
[collect_info]
...
colume_info=1,16,uid,int
column_info=1,17,item_name,varchar,20
column_info=1,18,item_price,int
column_info=1,19,collect_time,create_time
...
column_info 配置项中的内容是具体描述⼀列的, ⽤”,”分开, 其内容包含:
列的属性
取值为0或1. 0—表⽰该列只有动态数据(只存在于UpdateServer); 1—表⽰该列既有动态数据⼜有静态数据(既存在于UpdateServer ⼜存在于 ChunkServer).
列id
列在表中的唯⼀标识, 不可以被重⽤. 列id必须⼤于1, 系统保留id为1的⽤于表⽰主键.
列名
是⼀个长度不超过128位的字符串.
类型
列的数据类型.
列长度
代码⼊⼝:
保留列ID
:
static const uint64_t OB_ALL_MAX_COLUMN_ID = 65535;
// internal columns id
const uint64_t OB_NOT_EXIST_COLUMN_ID = 0;
const uint64_t OB_CREATE_TIME_COLUMN_ID = 2;
const uint64_t OB_MODIFY_TIME_COLUMN_ID = 3;
const int64_t OB_END_RESERVED_COLUMN_ID_NUM = 16;
const uint64_t OB_APP_MIN_COLUMN_ID = 16;
从上⾯定义可看到OceanBasew保留1-15列ID内部使⽤,应⽤⾃定义列的ID从16开始,最⼤65535。I
D为2和3的列对应记录创建时间与记录修改时间,这两个列ID不能⽤于其它列,⽽且这两个列的类型值为8()与9()这个在代码中有所检查,⽐如::
if (parse_ok && type == ObCreateTimeType)
{
if (has_create_time_column)
{
TBSYS_LOG(ERROR, "more than one column have create time type");
parse_ok = false;
}
else
{
has_create_time_column = true;
schema.set_create_time_column(id);
}
}error parse new
if (parse_ok && type == ObModifyTimeType)
{
if (has_modify_time_column)
{
TBSYS_LOG(ERROR, "more than one column have modify time type");
parse_ok = false;
}
else
{
has_modify_time_column = true;
schema.set_modify_time_column(id);
}
}
与L2462开始处:
if (parse_ok)
{
if (!has_create_time_column && has_create_time_id)
{
TBSYS_LOG(WARN, "schema file has no create_time column, and the default create_time column id is used");
parse_ok = false;
}
if (!has_modify_time_column && has_modify_time_id)
{
TBSYS_LOG(WARN, "schema file has no modify_time column, and the default modify_time column id is used");
parse_ok = false;
}
}
RowKey
表主键配置项,⼤致格式:
column_name1(column_length%column_type),column_name2(column_length%column_type),...
其中,括号部分的内容是可选的。
从Schema定义⽂件中读取RowKey定义的⼊⼝在:
index = 0;
for(vector<string>::iterator it = sections.begin();
it != d() && parse_ok; ++it)
{
if (strcmp(it->c_str(), STR_SECTION_APP_NAME) == 0)
{
continue;
}
if ( !parse_rowkey_info(it->c_str(), config, table_infos_[index]) )
{
parse_ok = false;
table_nums_ = 0;
break;
}
++index;
}
⽅法,从Schema定义⽂件中表列定义中读取“rowkey”属性值,其值由逗号分割的多个主键列组成:
bool ObSchemaManagerV2::parse_rowkey_info(const char* section_name, tbsys::CConfig&  config, ObTableSchema& schema)
{
bool parse_ok = true;
//parse rowkey column
const char* rowkey_column_str = NULL;
char* clone_column_str = NULL;
ObRowkeyInfo  rowkey_info;
vector<char*> column_list;
if (NULL != section_name)
{
rowkey_column_str = String(section_name, STR_ROWKEY);
}
if (NULL != rowkey_column_str)
{
clone_column_str = strdup(rowkey_column_str);
tbsys::CStringUtil::split(clone_column_str, ",", column_list);
int size = static_cast<int>(column_list.size());
for (int index = 0; parse_ok && index < size; ++index)
{
ObRowkeyColumn column;
parse_ok = parse_rowkey_column(column_list[index], column, schema);
if (parse_ok)
{
<_rowkey_info().add_column(column);
}
}
free(clone_column_str);
}
return parse_ok;
}
每个主键列完整定义形式:column_name(column_length%column_type), 括号当中的被称为compatible rowkey descriptions(什么⿁东西?),括号与括号的内容是可以省略的。先从表的列定义中根据colume_name查列定义(ID、长度、类型),如果不存在compatible rowkey descriptions就直接使⽤列定义相关属性,存在刚从compatible rowkey descriptions中解析列长度与类型,对应的⽅法是:
bool ObSchemaManagerV2::parse_rowkey_column(const char* column_str, ObRowkeyColumn& column, ObTableSchema& schema)
{
// column str like
// column_name(column_length%column_type)
bool parse_ok = true;
if (NULL != column_str)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。