InnoDB Plugin Fast Index Creation建索引期间不支持对表的读写
原文链接:http://blog.inkernel.info/archives/15.html
之前认为MySQL可以进行在线增加索引,增加索引时会调用handler::add_index接口,但近期调试时发现,在调用add_index之前,MySQL会关闭所有的handler。因此怀疑可能在add_index期间表是不允许被操作的。InnoDB Plugin的文档说建secondary index时表是可读的,但是实际调试过程中并非如此。
MySQL在线加索引是会关闭所有handler,从show processlist命令可以看到waitint for table。之前看到innodb buildin版本在线加辅助索引时还能对表进行操作是因为buildin版本在线建辅助索引还是进行了表拷贝,其他操作是在旧表上做的。Innodb_plugin的文档上应该不是说add_index时表一定可读(any writes to the table are blocked, but the data in the table may be read)。在manage key期间表也是不可以读的,而manage key比修改mysql的数据字典要慢一些。如果只在修改mysql数据字典时再加X锁应该也是可以的,但上层不是这样子做的。严格意义上来说,这不是真正的在线建索引。虽然在线建索引最终改表元数据还是要加互斥锁,但是这个时间应该是越短越好。至于维护索引一致性,可以通过重做日志实现。
MySQL上层代码分析
MySQL对表的Alter操作分为以下几种:
- ALTER_TABLE_METADATA_ONLY, No copy needed
- ALTER_TABLE_DATA_CHANGED, Data changes, copy needed
- ALTER_TABLE_INDEX_CHANGED, Index changes, copy might be needed
就是说如果need_copy_table变量是ALTER_TABLE_METADATA_ONLY,则不需要拷贝表,只需要修改mysql的数据字典;如果是ALTER_TABLE_DATA_CHANGED,则需要拷贝表;如果是ALTER_TABLE_INDEX_CHANGED,则可能拷贝也可能不拷贝。
分析几段MySQL上层的代码(均来自mysql_alter_table函数),以说明下 InnoDB Plugin建secondary index时的流程:
sql_table.cc:6842
/* 比较新旧表定义,确定是否需要拷贝到新表,need_copy_table_res变量在返回时被修改为ALTER_TABLE_INDEX_CHANGED */ |
sql_table.cc:7005
/* 下面判断alter_flags中本次在线修改所需要的标志位是否都已经设置,以确定可以进行在线修改 */ |
sql_table.cc:7108
/* 以上代码可以看到need_copy_table被赋值为ALTER_TABLE_METADATA_ONLY,所以不需要拷贝新表,new_table为NULL */ |
sql_table.cc:7145
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER)) |
PS:Innodb_plugin的fast index creation还有一些bug:
- If any of the indexed columns use the UTF-8 character encoding, MySQL will copy the table. This has been reported as MySQL Bug#33650.
- ALTER TABLE ADD INDEX may lead to table copying if there's numeric field(s) with non-default display width modificator specified. (Fixed in 5.1.47)
posted on 2011-09-07 23:37 Swimming Fish 阅读(385) 评论(0) 编辑 收藏 举报