MySQL 5.6.12的Innodb性能改进

简单的记录下,在MySQL5.6.12中innodb层的3点跟性能相关的改进
1.在文件操作部分,移除了许多sleep操作,而是改用condition wait
对应的bug http://bugs.mysql.com/bug.php?id=68588。 在Mark的测试中,有近一倍的性能提升
主要修改都几种在函数fil_flush中:
每个文件结构体node都增加了一个event:
fil_node_create:
     node->sync_event = os_event_create();
fil_node_free:      
  os_event_free(node->sync_event)

fil_flush:

当文件上已经有线程在做flush时:
5638                 if (node->n_pending_flushes > 0) {
5639                         /* We want to avoid calling os_file_flush() on
5640                         the file twice at the same time, because we do
5641                         not know what bugs OS's may contain in file
5642                         i/o */
5643
5644                         ib_int64_t sig_count =
5645                                 os_event_reset(node->sync_event);
5646
5647                         mutex_exit(&fil_system->mutex);
5648
5649                         os_event_wait_low(node->sync_event, sig_count);
5650
5651                         mutex_enter(&fil_system->mutex);
5652
5653                         if (node->flush_counter >= old_mod_counter) {
5654
5655                                 goto skip_flush;
5656                         }
5657
5658                         goto retry;
5659                 }

5661                 ut_a(node->open);
5662                 file = node->handle;
5663                 node->n_pending_flushes++;
5664
5665                 mutex_exit(&fil_system->mutex);
5666
5667                 os_file_flush(file);
5668
5669                 mutex_enter(&fil_system->mutex);
5670
5671                 os_event_set(node->sync_event);
5672
5673                 node->n_pending_flushes--;

 

好吧,我承认我摘录上述代码的目的,只是简单记录下innodb condition wait的用法…
2.用户线程在查找空闲block,会刷单个page,这可能导致sync所有的文件
用户线程做了single page flush后,加入一个IO异步请求队列后,会调用buf_flush_sync_datafiles.随后会唤醒IO线程,并在之后fsync所有的数据文件。          
该bzr主要修改包括:
* 所有batch flush操作异步进行(和以前一样)
buf_dblwr_flush_buffered_writes:
914         for (ulint i = 0; i < first_free; i++) {
915                 buf_dblwr_write_block_to_datafile(

916                         buf_dblwr->buf_block_arr[i], false);              // false表示异步写

917         }

* single page flush以寻找一个空闲块,这是同步操作
buf_flush_single_page_from_LRU->buf_flush_page->buf_flush_write_block_low->buf_dblwr_write_single_page
1130         /* We know that the write has been flushed to disk now

1131         and during recovery we will find it in the doublewrite buffer

1132         blocks. Next do the write to the intended position. */

1133         buf_dblwr_write_block_to_datafile(bpage, sync);      //该backtrace的sync为TRUE

buf_flush_page在多处被调用到,其增加了一个sync参数,用于表示该page flush操作需要同步还是异步进行。而在5.6.11中会在调用buf_flush_page后调用buf_flush_sync_datafiles()来sync所有的数据文件。
另外,有一种情况,在做SINGLE PAGE FLUSH时,采用异步的方式,backtrace如下:

row_import_for_mysql->buf_LRU_remove_pages->buf_flush_dirty_pages->buf_flush_or_remove_pages->buf_flush_page
这其实就是5.6的新特性ibd import功能的backtrace,后面单独开篇介绍

* 将single page flush的dblwr slot处理转移到IO线程

函数:buf_dblwr_update
当IO操作完成写一个page后,这个函数会被调用到,在5.6.12中会做两件事儿:
对于batch flush操作(BUF_FLUSH_LIST 或者BUF_FLUSH_LRU),当预留给batch flush的slot都全部完成刷新后(buf_dblwr->b_reserved = 0),会去sync数据文件(fil_flush_file_spaces(FIL_TABLESPACE)),将batch_running设为false,并发送完成信号
对于single page flush操作,找到当前page的slot,然后将其设置为未使用(in_use[i] = false),随后发送condition 信号(buf_dblwr->s_event)
这里采用顺序遍历,来寻找当前page的slot,是否存在效率问题?
而在5.6.11版本中,只考虑了batch flush操作。

* 移除对dblwr buffer中的sleep,改用condition wait

 写double write buffer时,如果已经在刷dblwr,以前是sleep 10ms,现在改成condition wait了,这里包括batch flush 和single page flush,这两者都增加了条件变量
当脏页刷新非常频繁时,会看到很明显的性能提升
*其他
另外一个没提到的修改是函数buf_flush_LRU_tail
在5.6.11的版本中,并没有对buf_flush_LRU的返回值进行处理。而在5.6.12中,增加了如下逻辑:
2092                 for (ulint j = 0;
2093                      j < scan_depth;
2094                      j += PAGE_CLEANER_LRU_BATCH_CHUNK_SIZE) {
2095 
2096                         ulint   n_flushed = 0;
2097 
2098                         /* Currently page_cleaner is the only thread
2099                         that can trigger an LRU flush. It is possible
2100                         that a batch triggered during last iteration is
2101                         still running, */
2102                         if (buf_flush_LRU(buf_pool,
2103                                           PAGE_CLEANER_LRU_BATCH_CHUNK_SIZE,
2104                                           &n_flushed)) {
2105 
2106                                 /* Allowed only one batch per
2107                                 buffer pool instance. */
2108                                 buf_flush_wait_batch_end(
2109                                         buf_pool, BUF_FLUSH_LRU);
2110                         }
2111 
2112                         if (n_flushed) {
2113                                 total_flushed += n_flushed;
2114                         } else {
2115                                 /* Nothing to flush */
2116                                 break;
2117                         }
2118                 }
3.优化batch flush的效率,之前的时间复杂度为O(N*N)
每个buffer pool实例增加了一个新的变量:
        const buf_page_t*       flush_list_hp;/*!< “hazard pointer”

used during scan of flush_list

while doing flush list batch.

Protected by flush_list_mutex */

根据注释,其在批量刷新时使用,用flush_list_mutex 来保护
buf_flush_set_hp :设置flush_list_hp指针,指向参数传递的page
buf_flush_update_hp:当flush_list上的block移除或者移动时,需要检查buf_flush_set_hp指针是否被其他正在扫描flush list的线程设置,如果flush_list_hp指向我们下一个将要扫描的page,则将其设置为NULL,表示需要重新扫描
有两个地方会调用到这个函数:
* 从flush list上移除一个page的时候(buf_flush_remove)
* 为flush list上的一个page重分配控制块,buf_flush_relocate_on_flush_list
buf_do_flush_list_batch:
在该函数的修改是核心部分,主要消除了在bug#69170中描述的o(n*n)的时间复杂度。所有作用于flush list的线程,都需要先检查flush_list_hp指针,
这里的方法很简单,从flush list的尾部开始扫描, 每次获取一个page后,将bp->flush_list_hp的指针指向该page的前一个, 然后释放bp->flush_list_mutex
然后执行该page的刷新
flushed = buf_flush_page_and_try_neighbors(

bpage, BUF_FLUSH_LIST, min_n, &count);

再次持有flush_list_mutex锁,查看bp->flush_list_hp是否发生变化,如果发生变化了,则表明该指针被其他线程设置了,也就是说,有其他线程对flush list做了操作,因此需要从flush list尾部重新开始扫描
在5.6.11的版本中,总是无条件的从尾部开始重新扫描。

 

原创文章,转载请注明: 转载自Simple Life

本文链接地址: MySQL 5.6.12的Innodb性能改进

Post Footer automatically generated by wp-posturl plugin for wordpress.


Comments

Leave a Reply

Your email address will not be published. Name and email are required


Current month ye@r day *