March 29, 2014

[MySQL5.7] 5.7版本针对临时表的优化

尽量临时表在实际在线场景中很少会去显式使用,但在某些运维场景还是需要到的,在MySQL5.7中,专门针对临时表做了些优化;大概扫了下代码,把一些要点及关键函数记录下。 #独立的tmp表空间,默认在data目录下建立一个命名为ibtmp1的临时表表空间;对于非压缩临时表,表空间内容存放到ibtmp1下面;对于压缩表,依然会为其在tmp目录下建立ibd文件; #server启动时会删除之前的ibtmp文件并重建(函数srv_open_tmp_tablespace) #临时表空间使用全局变量srv_tmp_space(5.7里所有对表空间的管理的代码被重构成类Tablespace) #无需为临时表记录redo log,因为临时表不做crash recovery;因此在针对临时表的大量操作直接disable redo (dict_disable_redo_if_temporary) #临时表专用的回滚段,回滚段同样被记录到临时表空间ibtmp1下面(trx_sys_create_noredo_rsegs); 降低和其他实体表的undo log存储产生竞争 尽管临时表无需做crash recovery,但依然要为其创建undo log表空间,因为可能在事务执行的过程中,需要回滚到某个savepoint; 临时表的undo log无需写redo (实体表的undo是需要写redo的) 128个回滚段中的32个回滚段(srv_tmp_undo_logs)专门预留给临时表操作(回滚段trx_rsegs_t被分为两类:m_redo及m_noredo) 针对purge操作,也做了修改,采用一个优先队列来进行操作(具体见函数TrxUndoRsegsIterator::set_next(),  purge_sys->purge_queue, 在函数trx_purge_rseg_get_next_history_log中往队列加undo,创建临时表回滚段调用trx_sys_create_noredo_rsegs) 其他相关函数:trx_sysf_rseg_find_free,查找回滚段(get_next_redo_rseg及get_next_noredo_rseg, trx_assign_rseg_low) 对undo的修改详细见该patch: http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5832 #临时表的定义可以存放在内存,无需持久化到磁盘; 无需将临时表的元数据信息写入到系统表(对于临时表,create_table_def直接调用dict_build_tablespace && dict_table_add_to_cache 创建索引时同样区分对待(row_create_index_for_mysql) 其他相关函数:dict_build_index_def,dict_create_index_tree,dict_recreate_index_tree(include/dict0crea.h),这些函数用于对表元数据进行操作而无需更新系统表 #降低对临时表的锁约束,因为临时表只对当前client可见; 例如无需对更新临时表的二级索引页设置trx id, 不做可见性判断(lock_clust_rec_cons_read_sees, lock_sec_rec_cons_read_sees, lock_sec_rec_read_check_and_lock),不会去加innodb层表锁 (lock_table) 甚至对临时表而言记录锁也是多余的。 #避免对临时表使用change buffer.  另外在ibtmp表空间中的临时表也不为其分配Ibuf  bitmap page(fsp_fill_free_list) #增加了一个新的information schema表INNODB_TEMP_TABLE_INFO来显示临时表信息 root@test 12:41:54>create temporary table t1 (a int); Query OK, 0 rows […]