文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

InnoDB IO路径源码的示例分析

2023-06-04 13:33

关注

这篇文章主要介绍InnoDB IO路径源码的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

InnoDB实现IO Flush通过“os_file_flush”宏收敛,macro展开后为”os_file_flush_func”。

接下来,我们重点看一下,还有其它哪些场景会调用到这个os_file_flush_func函数:

buf_dblwr_init_or_load_pages中,在double buffer 做crash恢复时,如果设置了reset_space_ids为”true”

fil_create_new_single_table_tablespace中,创建表数据文件时

fil_user_tablespace_restore_page中,从double writer buffer中copy page时

fil_tablespace_iterate中,如果iterate page失败时,会做一次sync

os_file_set_size中,在文件新创建时初始化文件大小时

从上面可以看出,直接调用os_file_flush_func还是非常少的。那么系统中还有一些是调用os_file_flush_func的上层函数fil_flush:

buf_dblwr_flush_buffered_writes中,flush double write buffer到disk

buf_dblwr_write_single_page中,单页flush到disk中

buf_flush_write_block_low中,flush block到disk中,一般在调double write buffer“buf_dblwr_flush_buffered_writes“之后调用

buf_LRU_remove_pages中,delete某个tablespace中的page时,做sync调用

fil_rename_tablespace中,rename一个tablespace时调用

fil_extend_space_to_desired_size中,extend space时

fil_flush_file_spaces中,flush 批量tablespace的page时,被ha_innodb的force checkpoint时调用,shutdown DB时调用等

log_io_complete中,log io完成时,checkpoint write以及其它,是否调用受sync方式影响,非commit依赖

log_write_up_to中,commit事务时,这个是重点,innodb 的log file都会调用,而且是同步

create_log_files_rename中,rename log file时

innobase_start_or_create_for_mysql中,创建新的文件时

在fil_flush函数中,所有文件的flush cache行为受fil_system->mutex保护。因此不管是data file还是log file,文件级别的flush是串化的。那么具体是怎么来控制的呢?

检查file node中的n_pending_flushes,如果大于“0”就一直retry

如果为“0”,进入flush阶段,在正式开始flush之前,先将n_pending_flushe加“1”,这个操作受上文提到的“fil->mutex“保护

调用“os_file_flush“ flush完成之后,n_pending_flushes减“1”,也同样由“fil->mutex“保护

下面是MySQL中retry的代码:

retry:

if (node->n_pending_flushes > 0) {

ib_int64_t sig_count =

                os_event_reset(node->sync_event);

            mutex_exit(&fil_system->mutex);

            os_event_wait_low(node->sync_event, sig_count);

            mutex_enter(&fil_system->mutex);

if (node->flush_counter >= old_mod_counter) {

goto skip_flush;

            }

goto retry;

        }

下面是MySQL中flush的代码:

        ut_a(node->open);

        file = node->handle;

        node->n_pending_flushes++;

        mutex_exit(&fil_system->mutex);

        os_file_flush(file);

        mutex_enter(&fil_system->mutex);

        os_event_set(node->sync_event);

        node->n_pending_flushes--;

        node->flush_size = node->size;

上面提到的逻辑,对于log file也同样处理。Log file的tablespace为log space。对于log file,还受到log_sys->mutex的保护,在log_write_up_to函数中。

Log file的flush行为收敛到“log_write_up_to”函数体中,再调用fil_flush,最终走到os_file_flush_func。

MySQL在commit的时候,如果”innodb_flush_log_at_trx_commit=1”时,调用两次同步的log_write_up_to,一次是innobase log file 的flush,一次是bin log的flush。

如果关掉bin log,则在ordered_commit函数中,不会走sync_blog分支。以下是关掉和不关掉时,innobase flush log file的执行路径。

不带binlog时的Innobase 的pstack如下:

fsync,os_file_fsync,os_file_flush_func,fil_flush,log_write_up_to,trx_flush_log_if_needed_low,trx_flush_log_if_needed,trx_commit_complete_for_mysql,innobase_commit,ha_commit_low,TC_LOG_DUMMY::commit,ha_commit_trans,trans_commit_stmt,mysql_execute_command,mysql_parse,dispatch_command,do_command,do_handle_one_connection,handle_one_connection,start_thread,clone

带Binlog的flush pstack如下:

fsync,os_file_fsync,os_file_flush_func,fil_flush,log_write_up_to,innobase_flush_logs,flush_handlerton,plugin_foreach_with_mask,ha_flush_logs,MYSQL_BIN_LOG::process_flush_stage_queue,MYSQL_BIN_LOG::ordered_commit,MYSQL_BIN_LOG::commit,ha_commit_trans,trans_commit_stmt,mysql_execute_command,mysql_parse,dispatch_command,do_command,do_handle_one_connection,handle_one_connection,start_thread,clone

从上面大致的调用来看,log_write_up_to()和log_io_complete()将是重点,因为这些flush在file级别是串行的,commit时的rt主要由这些串化带来。

接下来我们看一下log_write_up_to的调用者都有那些:

buf_flush_write_block_low,在force flush中调用,保证日志必须先于数据落地,刷脏页时,由page_cleaner_do_flush_batch()发起调用到此函数

innobase_flush_logs,在commit时调用,主要由flush binlog分支调用

trx_flush_log_if_needed_low,在commit时调用,主要由flush innodb log file时调用

log_buffer_flush_to_disk,log buffer刷日志到disk

log_buffer_sync_in_background,后台线程同步log buffer到disk,由srv_master_thread 线程调srv_sync_log_buffer_in_background()调用到,每秒一次

log_flush_margin,主要为腾挪log buffer空间时调用

log_checkpoint,主要在做checkpoint时调用到,由srv_master线程调用srv_master_do_idle_tasks(),每秒做一次

log_io_complete()函数的调用情况:

fil_aio_wait,aio wait中如果是log io将会调用此方法

从上面分析可以看到,主要影响RT比较严重的还是因为刷脏页导致的log_sys->mutex争用。另外,log_buffer_sync_in_background和log_checkpoint,这两个都是由后台srv_master_thread线程每隔一秒调用到。

但是这两个方法不一定会执行fil_flush,所以不是影响的主因。gdb挂上去后,大致会走到fil_flush争用的pstack如下:

Breakpoint 13, fil_flush   (space_id=4294967280, from=FLUSH_FROM_LOG_WRITE_UP_TO) at   /u01/mysql-5.6/storage/innobase/fil/fil0fil.cc:64786478      {(gdb) bt#0    fil_flush (space_id=4294967280, from=FLUSH_FROM_LOG_WRITE_UP_TO) at   /u01/mysql-5.6/storage/innobase/fil/fil0fil.cc:6478#1    0x0000000000c890e5 in log_write_up_to (lsn=,   wait=, flush_to_disk=1, caller=) at   /u01/mysql-5.6/storage/innobase/log/log0log.cc:1674#2    0x0000000000d79d26 in buf_flush_write_block_low (sync=false,   flush_type=BUF_FLUSH_LIST, bpage=0x7fd706332330) at   /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:902#3    buf_flush_page (buf_pool=, bpage=0x7fd706332330,   flush_type=BUF_FLUSH_LIST, sync=) at   /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:1061#4    0x0000000000d7a43e in buf_flush_try_neighbors (space=0,   offset=offset@entry=5, flush_type=flush_type@entry=BUF_FLUSH_LIST,   n_flushed=n_flushed@entry=1, n_to_flush=n_to_flush@entry=250)      at /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:1271#5    0x0000000000d7b1b1 in buf_flush_page_and_try_neighbors   (flush_type=BUF_FLUSH_LIST, count=, n_to_flush=250,   bpage=) at /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:1355#6    buf_do_flush_list_batch (buf_pool=buf_pool@entry=0x1f817d8,   min_n=min_n@entry=250, lsn_limit=lsn_limit@entry=18446744073709551615) at   /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:1623#7    0x0000000000d7b308 in buf_flush_batch (flush_type=BUF_FLUSH_LIST,   lsn_limit=18446744073709551615, min_n=,   buf_pool=0x1f817d8) at /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:1693#8    buf_flush_list (min_n=,   n_processed=n_processed@entry=0x7fc6dd7f9bd8, lsn_limit=18446744073709551615)   at /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:1939#9    0x0000000000d7c79b in page_cleaner_do_flush_batch   (lsn_limit=18446744073709551615, n_to_flush=) at   /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:2216#10 buf_flush_page_cleaner_thread   (arg=) at   /u01/mysql-5.6/storage/innobase/buf/buf0flu.cc:2588#11 0x00007fd950ef9dc5 in start_thread ()   from /lib64/libpthread.so.0#12 0x00007fd94ef4a28d in clone () from   /lib64/libc.so.6Breakpoint 5, fil_flush   (space_id=4294967280, from=FLUSH_FROM_LOG_IO_COMPLETE) at   /u01/mysql-5.6/storage/innobase/fil/fil0fil.cc:64786478      {(gdb) bt#0    fil_flush (space_id=4294967280, from=FLUSH_FROM_LOG_IO_COMPLETE) at   /u01/mysql-5.6/storage/innobase/fil/fil0fil.cc:6478#1    0x0000000000c86c78 in log_io_complete (group=) at   /u01/mysql-5.6/storage/innobase/log/log0log.cc:1239#2    0x0000000000db5a4b in fil_aio_wait (segment=segment@entry=1) at   /u01/mysql-5.6/storage/innobase/fil/fil0fil.cc:6463#3    0x0000000000d09ba0 in io_handler_thread (arg=) at   /u01/mysql-5.6/storage/innobase/srv/srv0start.cc:498#4    0x00007fb818efddc5 in start_thread () from /lib64/libpthread.so.0#5    0x00007fb816f4e28d in clone () from /lib64/libc.so.61: *node = {space = 0x30aa218, name =   0x30aa948 "/mnt/mysql-redo/my3308/data/ib_logfile0", open = 1,   handle = 10, sync_event = 0x30aa980, is_raw_disk = 0, size = 262144,   n_pending = 0, n_pending_flushes = 0,    being_extended = 0, modification_counter = 49, flush_counter = 41,   flush_size = 262144, chain = {prev = 0x0, next = 0x30aaa78}, LRU = {prev =   0x0, next = 0x0}, magic_n = 89389}

因此,总结起来,应该是commit做的两次fsync加上一次page cleaner做的log_write_up_to()。另外,还有一个fil_aio_wait完成时,如果是log io,就会做一次log_io_complete()。

这四次fsync都会对用户的rt有影响,commit的两次无可避免,后面两次最多也就是调整频率。另外是否可以改变fsync的方式?这个读者可以思考。

比oracle实现差,oracle不会作强制的,我记得是给一个标记,策略还是按redo自己的策略来做。oracle的实现应该是考虑到这一点了.


以上是“InnoDB IO路径源码的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网行业资讯频道!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯