首页 > 学院 > 综合知识 > 正文

Innodb undo之 undo物理构架的初始化

2022-07-19 11:53:41
字体:
来源:转载
供稿:网友
  水平有限,如果有误请指出。
  一直以来未对Innodb 的undo进行好好的学习,最近刚好有点时间准备学习一下,通过阿里内核月报和自己看代码的综合总结一下。本文环境:
 
  代码版本 percona 5.7.22
  参数 innodb_undo_tablespaces = 4 及使用了4个undo tablespace
  参数 innodb_rollback_segments = 128
  本文描述使用如上参数的设置。
 
  一、undo 表空间物理文件的建立
  本过程调用函数srv_undo_tablespaces_init进行,栈帧如下:
 
  #0  srv_undo_tablespaces_init (create_new_db=true, n_conf_tablespaces=4, n_opened=0x2ef55b0)
      at /root/mysqlc/percona-server-locks-detail-5.7.22/storage/innobase/srv/srv0start.cc:824#1  0x0000000001bbd7e0 in innobase_start_or_create_for_mysql () at /root/mysqlc/percona-server-locks-detail-5.7.22/storage/innobase/srv/srv0start.cc:2188#2  0x00000000019ca74e in innobase_init (p=0x2f2a420) at /root/mysqlc/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:4409#3  0x0000000000f7ec2a in ha_initialize_handlerton (plugin=0x2fca110) at /root/mysqlc/percona-server-locks-detail-5.7.22/sql/handler.cc:871#4  0x00000000015f9edf in plugin_initialize (plugin=0x2fca110) at /root/mysqlc/percona-server-locks-detail-5.7.22/sql/sql_plugin.cc:1252
  本过程主要有如下几个步骤:
 
  根据参数innodb_undo_tablespaces 的配置通过调用srv_undo_tablespace_create分别进行文件建立,默认建立的大小为10M:
  for (i = 0; create_new_db && i < n_conf_tablespaces; ++i) //n_conf_tablespaces 为innodb_undo_tablespaces的配置的个数/** Default undo tablespace size in UNIV_PAGEs count (10MB). */const ulint SRV_UNDO_TABLESPACE_SIZE_IN_PAGES =
      ((1024 * 1024) * 10) / UNIV_PAGE_SIZE_DEF;
  ...
          err = srv_undo_tablespace_create(
              name, SRV_UNDO_TABLESPACE_SIZE_IN_PAGES); //建立undo文件...
  
  分别对4个undo tablespace调用srv_undo_tablespace_open 其主要调用fil_space_create 和 fil_node_create将新建立的undo tablespace加入Innodb的文件体系。
  for (i = 0; i < n_undo_tablespaces; ++i) {
  ....
  err = srv_undo_tablespace_open(name, undo_tablespace_ids[i]); //打开UNDO文件 建立 file node...
  }
  分别对4个undo tablespace 进行fsp header初始化
  for (i = 0; i < n_undo_tablespaces; ++i) {
              fsp_header_init( //初始化fsp header 明显 space id 已经写入
                  undo_tablespace_ids[i],
                  SRV_UNDO_TABLESPACE_SIZE_IN_PAGES, &mtr); //SRV_UNDO_TABLESPACE_SIZE_IN_PAGES 默认的undo大小 10MB
 
  做完这个步骤只是生成了4个大小为10MB的 undo tablespace文件,并且已经加入到Innodb文件体系,但是里面没有任何类容。
 
  二、ibdata中system segment header的初始化
  本步骤调用 trx_sys_create_sys_pages->trx_sysf_create进行,本步骤除了初始化transaction system segment以外还会初始化其header( ibdata page no 5))信息如下:
 
  /* Create the trx sys file block in a new allocated file segment */
      block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
                  mtr); //建立segment
      buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
      ut_a(block->page.id.page_no() == TRX_SYS_PAGE_NO);
      page = buf_block_get_frame(block); //获取内存位置
      mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_TRX_SYS, //写入block 的类型
               MLOG_2BYTES, mtr);
      ...    /* Start counting transaction ids from number 1 up */
      mach_write_to_8(sys_header + TRX_SYS_TRX_ID_STORE, 1); // 初始化TRX_SYS_TRX_ID_STORE
      /* Reset the rollback segment slots.  Old versions of InnoDB
      define TRX_SYS_N_RSEGS as 256 (TRX_SYS_OLD_N_RSEGS) and expect
      that the whole array is initialized. */
      ptr = TRX_SYS_RSEGS + sys_header;
      len = ut_max(TRX_SYS_OLD_N_RSEGS, TRX_SYS_N_RSEGS)
          * TRX_SYS_RSEG_SLOT_SIZE;//TRX_SYS_OLD_N_RSEGS 为256个
      memset(ptr, 0xff, len); //将slot的信息的全部初始化为ff
      ptr += len;
      ut_a(ptr <= page + (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END));    /* Initialize all of the page.  This part used to be uninitialized. */
      memset(ptr, 0, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page - ptr); //将剩下的空间设置为0x00
      mlog_log_string(sys_header, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
              + page - sys_header, mtr);    /* Create the first rollback segment in the SYSTEM tablespace */
      slot_no = trx_sysf_rseg_find_free(mtr, false, 0);
      page_no = trx_rseg_header_create(TRX_SYS_SPACE, univ_page_size,
                       ULINT_MAX, slot_no, mtr); //将第一个slot固定在ibdata中
  完成了这一步过后ibdata的 block 5 就初始化完了,而且我们看到所有的rollback segment slots 都初始化完成(源码所示有256个,实际上最多只会有128个,其中0号solt固定在ibdata中),注意这里的槽大小是TRX_SYS_RSEG_SLOT_SIZE设置的大小为8字节,4字节space id ,4字节 page no,它们会指向 rollback segment header所在的位置。
 
  三、进行rollback segment header的初始化
  调用 trx_sys_create_rsegs进行:
 
  说明一下关于innodb_undo_logs参数和innodb_rollback_segments参数,他们作用就是设置rollback segment 的个数,本文以128为例。
  根据注释和代码innodb_undo_logs已经是个淘汰的参数,应该用innodb_rollback_segments代替。
  这两个参数默认是就是TRX_SYS_N_RSEGS及 128 其实不用设置的。本文也用128进行讨论。

(编辑:错新网)

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表