Innodb检查点和redo写盘时机

一、LSN

innodb的lsn和oracle的scn一样,是一个重要的概念。是整个数据库数据同步的一种统一辨别标准,在很多地方都使用到了LSN比如

    在flush list中正是是使用page的oldest lsn作为链表的条件
    参考buf_page_t类中的 lsn_t oldest_modification;变量

    在checkpoint中记录的也是lsn
    参考宏 LOG_CHECKPOINT_LSN

    在物理文件中每个page最后的刷新lsn
    参考宏FIL_PAGE_LSN

    在写日志落盘的时候也是以lsn为标准的
    参考函数log_write_up_to

    实际上lsn就是表示的日志量的字节数,是一个累加的值,在5.7中表现为:

    /*Typeusedforalllogsequencenumberstorageandarithmetics*/typedefib_uint64_tlsn_t;

    及一个8字节非负的整数。最大值及2的64次方。有了这种物理上概念,lsn很容易换算为当前日志的偏移量。

    二、innodb中检查点的理解

    这里我只讨论正常运行的情况下检查点。innodb中类似oracle的增量检查点。正常运行checkpoint是由master线程触发。我们知道脏数据通过page clean线程和lru manager线程是在不断写盘的,那么在进行异常重启的的时候我们必须要知道一个恢复的起点,但是这个起点是不能记录在内存中必要固化到磁盘,恢复的时候读取这个点以后的redo进行恢复,而checkpoint就是完成这个事情下面是checkpoint的执行流程。

    正常情况下master线程会每秒进行检查点其作用有(参考log_checkpoint函数):

      检查是否有自上次检查点以来的脏数据写盘了。

      如果有则在redo里面会为每个修改过的文件写入MLOG_FILE_NAME,完成后写入一个总MLOG_CHECKPOINT(参考fil_names_clear函数)。
      1、MLOG_FILE_NAME主要记录至上次检查点以来更改过的数据文件。
      2、MLOG_CHECKPOINT主要记录检查点的lsn。
      这个步骤会遍历fil_system->named_spaces用于查找是否有自上次检查点以来修改过的文件链表。

      如果有则在redo log header中写入相应的检查点信息包含(异步写)。

      实际上我们可以理解检查点就是由master线程每秒醒来查看一下脏数据写到哪里了,然后将其记录到合适的位置,以备carsh recovery使用。(参考srv_master_thread函数)

      三、show engine innodb中的检查点信息

      下面是一个没有任何更新操作的库的信息如下:

      Logsequencenumber697794162Logflushedupto697794162Pagesflushedupto697794162Lastcheckpointat697794153

        Log sequence number:已经写到log buffer中的lsn。
        参考mtr_t::Command::finish_write函数。

        Log flushed up to:已经写到日志文件的redo的lsn。
        参考log_write_flush_to_disk_low函数。

        Pages flushed up to :此lsn之前的脏数据都已经写到了数据文件。
        参考log_buf_pool_get_oldest_modification函数。

        Last checkpoint at :最后一次检查点记录到了什么位置。
        参考next_checkpoint_lsn函数。

        下面是这段输出的源码:

        fprintf(file,"Logsequencenumber"LSN_PF"\n""Logflushedupto"LSN_PF"\n""Pagesflushedupto"LSN_PF"\n""Lastcheckpointat"LSN_PF"\n",log_sys->lsn,log_sys->flushed_to_disk_lsn,log_buf_pool_get_oldest_modification(),log_sys->last_checkpoint_lsn);

        一般来讲Log sequence number >Log flushed up to> Pages flushed up to>Last checkpoint at ,但是这里注意一下。Pages flushed up to 697794162和Last checkpoint at 697794153,显然这里是一个没有任何操作的库所以Pages flushed up to应该和Last checkpoint at 相等,但是这里存在差值,差值为:

          697794162-697794153 = 9

          这刚好是MLOG_CHECKPOINT的长度源码片段如下:

          oldest_lsn<=log_sys->last_checkpoint_lsn+SIZE_OF_MLOG_CHECKPOINT/**SizeofaMLOG_CHECKPOINTrecordinbytes.TherecordconsistsofaMLOG_CHECKPOINTbytefollowedbymach_write_to_8(checkpoint_lsn).*/#defineSIZE_OF_MLOG_CHECKPOINT9
          四、我所debug的几种redo写盘的时机

            master 线程每秒调用 栈帧(可能是idle可能是active 和检测是否需要插入缓存合并有关)

            #0log_group_write_buf(group=0x33f29f8,buf=0x7fffa5b38000"\200\024",len=512,pad_len=0,start_lsn=697764864,new_data_offset=166)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1145#10x0000000001a50f95inlog_write_up_to(lsn=697765068,flush_to_disk=true)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1493#20x0000000001a51163inlog_buffer_sync_in_background(flush=true)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1553#30x0000000001b84bd1insrv_sync_log_buffer_in_background()at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/srv/srv0srv.cc:2312#40x0000000001b85666insrv_master_do_idle_tasks()at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/srv/srv0srv.cc:2586#50x0000000001b85b6binsrv_master_thread(arg=0x0)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/srv/srv0srv.cc:2744

              master 线程每秒checkpoint调用 (可能是idle可能是active 和检测是否需要插入缓存合并有关)

              #0log_group_write_buf(group=0x33f29f8,buf=0x7fffa5a38000"\200\024\002",len=1024,pad_len=0,start_lsn=697789952,new_data_offset=139)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1145#10x0000000001a50f95inlog_write_up_to(lsn=697790725,flush_to_disk=true)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1493#20x0000000001a52247inlog_checkpoint(sync=true,write_always=false)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1934#30x0000000001b856f2insrv_master_do_idle_tasks()at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/srv/srv0srv.cc:2596#40x0000000001b85b6binsrv_master_thread(arg=0x0)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/srv/srv0srv.cc:2744

                page clean 线程调用 栈帧

                #0log_group_write_buf(group=0x33f29f8,buf=0x7fffa5a38000"\200\024\002",len=13312,pad_len=1024,start_lsn=697778176,new_data_offset=468)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1145#10x0000000001a50f95inlog_write_up_to(lsn=697790015,flush_to_disk=true)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1493#20x0000000001c704c7inbuf_flush_write_block_low(bpage=0x7fffc0cae940,flush_type=BUF_FLUSH_LIST,sync=false)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/buf/buf0flu.cc:1035#30x0000000001c70ceainbuf_flush_page(buf_pool=0x33247d8,bpage=0x7fffc0cae940,flush_type=BUF_FLUSH_LIST,sync=false)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/buf/buf0flu.cc:1237#40x0000000001c717f4inbuf_flush_try_neighbors(page_id=...,flush_type=BUF_FLUSH_LIST,n_flushed=0,n_to_flush=25)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/buf/buf0flu.cc:1466

                  当前线程commit 调用栈帧如下:

                  #0log_group_write_buf(group=0x33f29f8,buf=0x7fffa5a38000"\200\024\002",len=2560,pad_len=0,start_lsn=697762816,new_data_offset=230)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1145#10x0000000001a50f95inlog_write_up_to(lsn=697765030,flush_to_disk=true)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1493#20x0000000001a51087inlog_buffer_flush_to_disk(sync=true)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/log/log0log.cc:1524#30x00000000019a9157ininnobase_flush_logs(hton=0x2e9fdd0,binlog_group_flush=true)at/root/mysql5.7.14/percona-server-5.7.14-7/storage/innobase/handler/ha_innodb.cc:4407#40x0000000000f65893inflush_handlerton(thd=0x0,plugin=0x7ffff03588e8,arg=0x7ffff0358944)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:2606#50x00000000015d7716inplugin_foreach_with_mask(thd=0x0,func=0xf65835<flush_handlerton(THD*,plugin_ref,void*)>,type=1,state_mask=4294967287,arg=0x7ffff0358944)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/sql_plugin.cc:2318#60x0000000000f658efinha_flush_logs(db_type=0x0,binlog_group_flush=true)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/handler.cc:2617#70x000000000185733dinMYSQL_BIN_LOG::process_flush_stage_queue(this=0x2e02c80,total_bytes_var=0x7ffff0358a88,rotate_var=0x7ffff0358a87,out_queue_var=0x7ffff0358a78)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8541#80x000000000185899finMYSQL_BIN_LOG::ordered_commit(this=0x2e02c80,thd=0x7fff2c000b70,all=false,skip_commit=false)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9189#90x000000000185700cinMYSQL_BIN_LOG::commit(this=0x2e02c80,thd=0x7fff2c000b70,all=false)at/root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8440#100x0000000000f63df8inha_commit_trans(thd=0x7fff2c000b70,all=false,ignore_global_read_lock=false)
Copyright © 2002-2019 测速网 https://www.inhv.cn/ 皖ICP备2023010105号 城市 地区 街道
温馨提示:部分文章图片数据来源与网络,仅供参考!版权归原作者所有,如有侵权请联系删除!
热门搜索