Innodb物理存储结构系列2 行记录格式

前一篇讨论了Innodb system,表空间,文件的关系及数据结构,这一篇记录下Innodb行记录的格式。

前提:
  1. server层和innodb层都有自己对于record的记录格式,需要进行转换。
  2. 物理文件上的记录存储,需要内存中的数据结构进行对应(任何数据都需要在内存中进行处理),进行存取的转换。

1. 测试case:

 create table `pp` (
  `id` int(11) default null,
  `name1` varchar(100) default null,
  `name2` char(10) default null
) engine=innodb default row_format: compact

insert into pp values(11,‘xpchild1‘,‘xpchild2‘);

2. 重要的数据结构:

  

    struct row_prebuilt_struct{
        mysql_row_templ_t* mysql_template;  server层的记录格式
        ins_node_t*    ins_node;        innodb层的数据结构
    }

    /* Insert node structure */
    struct ins_node_struct{
        dtuple_t*    row;            写入的行row
    }
    /** Structure for an SQL data tuple of fields (logical record) */
    struct dtuple_struct {
        dfield_t fields;            row记录的fields列表
    }
    /** Structure for an SQL data field */
    struct dfield_struct{
        void *data;                row记录中一个字段的定义
    }

2. 写入及转换过程:

  1. 准备过程:

    简要记录一下:

    1.1: 进入并发控制:进入innodb层的线程受限制,排队进入
        innodb_srv_conc_enter_innodb(prebuilt->trx);
    1.2: 创建node && row元组数据结构
        node = ins_node_create(INS_DIRECT, table, prebuilt->heap);
        row = dtuple_create(prebuilt->heap,dict_table_get_n_cols(table));
    1.3: 判断是否是compact格式: dict_table_is_comp(prebuilt->table)

  2. 内存--内存之间的转换: mysql server层到innodb层

    row_mysql_convert_row_to_innobase:

    for (i = 0; i < prebuilt->n_template; i++)
      templ = prebuilt->mysql_template + i;    从mysql层取出来temp1,
      dfield = dtuple_get_nth_field(row, i);    从row中取出来dfield,
      row_mysql_store_col_in_innobase_format(....);  然后用temp1去填充。

    

  3. 内存->磁盘文件的转换:转换tuple到记录rec

    先来看一下innodb存储的格式:

      

    说明:

1. len_arr: 记录的是变长column的长度,定长的不记录。
2. null_bits: 记录哪一个column是null值,因为null的column不占用其他空间
3. extra_bytes: 一共5个字节,记录了: Deleted_flag, Min_rec_flag, N_owned, Next_recorder等信息。
4. row_id: 因为innodb使用聚簇索引表,如果定义了pk,这里就是pk的值,如果没有,innodb会自动生成一个row_id.
5. trx_id: 记录事务id
6. roll_ptr: 回滚段地址,用于回滚和mvcc
7. id, name1, name2表示表pp的字段值

    3.1 分配row_id:
        row_ins_alloc_row_id_step: 判断是否是pk cluster表。
        如果不是,就分配一个rowid。dict_sys_get_new_row_id,
        然后填充到dict_sys_write_row_id(node->row_id_buf, row_id);

    

    3.2 生成系统index
      node->index = dict_table_get_first_index(node->table);
      系统自动为没有index的表,生成了一个叫GEN_CLUST_INDEX的index。本身不存在。
        /* "GEN_CLUST_INDEX" is the name reserved for Innodb default system primary index. */

    

    3.3 计算rec的长度:
        extra_size = REC_N_NEW_EXTRA_BYTES + UT_BITS_IN_BYTES(index->n_nullable);
        这里计算的extra_size=6,
        null_bits的计算方式是:#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8)

        遍历每一个column,计算column的长度占用的空间,以及存储数据所需要的空间。

条件1:fixed_length不占用len_arr.
条件2:如果是变长,且定义的最大长度< =255, 则len占用1个bytes。
条件3:如果是变长,且定义的长度>255, 但实际长度<128,则len占用1个bytes。
条件4: 如果是变长,且定义的长度>255, 但实际长度>=128,或者overflow了,则len占用2个bytes

/* If the maximum length of a variable-length field
        is up to 255 bytes, the actual length is always stored
        in one byte. If the maximum length is more than 255
        bytes, the actual length is stored in one byte for
        0..127.  The length will be encoded in two bytes when
        it is 128 or more, or when the field is stored externally. */

        if (field->fixed_len) {
            ut_ad(len == field->fixed_len);
            /* dict_index_add_col() should guarantee this */
            ut_ad(!field->prefix_len
                  || field->fixed_len == field->prefix_len);
        } else if (dfield_is_ext(&fields[i])) {
            ut_ad(col->len >= 256 || col->mtype == DATA_BLOB);
            extra_size += 2;
        } else if (len < 128
               || (col->len < 256 && col->mtype != DATA_BLOB)) {
            extra_size++;
        } else {
            /* For variable-length columns, we look up the
            maximum length from the column itself.  If this
            is a prefix index column shorter than 256 bytes,
            this will waste one byte. */
            extra_size += 2;
        }

  

  注意:之所以对于定义>255的,可能使用1个或者2个字节,兼顾了空间使用的效率。

      最终计算出来的结果是:len_arr=1; null_bits=1;

  

  3.4 写入rec内容:
    根据前面获取的size,然后把字段的内容写入的buf中,最后写入到page中。

  

注意: varchar 在使用的时候,并不是大于255就一定会使用2个字节存储长度。 所以varchar(>255)比小于255的多使用空间的说法,在compact格式下,是不准确的。

Innodb物理存储结构系列2 行记录格式,布布扣,bubuko.com

时间: 2024-10-25 12:01:24

Innodb物理存储结构系列2 行记录格式的相关文章

Innodb物理存储结构系列1

本篇先介绍 下Innodb表空间,文件相关的内存数据结构. 1. 数据结构 Innodb的tablespace和文件的关系,是一对多的关系,先来看三个结构体 1. fil_system_struct: 表示Innodb的表空间内存cache,innodb一共包括两类tablespace,即 #define FIL_TABLESPACE 501 /*!< tablespace */ #define FIL_LOG 502 /*!< redo log */ 而fil_tablespace有包括了两

innodb的存储结构

如下所示,innodb的存储结构包含:表空间,段,区,页(块),行 innodb存储结构优化的标准是:一个页里面存放的行数越多,其性能越高 表空间:零散页+段 独立表空间存放的是:数据.索引.插入缓冲. 共享表空间存放的是:撤销信息.系统事务信息.二次写缓冲.共享表空间扩展后就不会回缩了. 段:存储引擎自动管理 区:由64个连续的页组成,每个页大小为16K(每个区大小为1M),对于大的数据段,innodb存储引擎每次最多可以申请4个  区,以此来保证数据的顺序性能.在每个段开始都有32个页大小的

MySQL InnoDB 逻辑存储结构

MySQL InnoDB 逻辑存储结构 从InnoDB存储引擎的逻辑结构看,所有数据都被逻辑地存放在一个空间内,称为表空间,而表空间由段(sengment).区(extent).页(page)组成.ps:页在一些文档中又称块(block). InnoDB存储引擎的逻辑存储结构大致如下: 一.表空间(table space) 表空间分为了两种,这里简单的概括一下: 1. 独立表空间:每一个表都将会生成以独立的文件方式来进行存储,每一个表都有一个.frm表描述文件,还有一个.ibd文件. 其中这个文

Oracle的物理存储结构

Oracle数据库的体系结构是从某一角度来分析数据库的组成,工作过程以及数据库如何管理和组织数据的,主要包括物理存储结构,逻辑存储结构,内存结构以及进程结构. Oracle的物理存储结构: Oracle物理存储结构主要包括三种类型的物理文件,分别是数据文件(*.dbf),控制文件(*.ctl)和重做日志文件(*.log). 1. 数据文件 数据文件主要是存储数据的文件.例如,数据文存储的表的记录和索引.在这些数据文件中,如果用户频繁的访问某些数据,那么这些数据就会被存储在内存的缓冲区中.当对这些

InnoDB逻辑存储结构

从InnoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为表空间(tablespace).表空间又由段(segment).区(extent).页(page)组成.页在一些文档中有时也称为(block),InnoDB存储引擎的逻辑存储结构大致如图: 表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中.默认情况下InnoDB存储引擎有一个共享表空间ibdata1,即所有数据都存放在这个表空间内.如果用户启动了innodb_file_per_tab

Postgresql物理存储结构

Postgresql目前不支持使用裸设备和块设备. Postgresql的属于 Relation:表示表或索引. Tuple:表示表中的行. Page:表示在磁盘中的数据块. Buffer:表示在内存中的数据块. Page结构 Page默认大小为8KB,最大32KB,一个数据块中可存放多行的数据.块中的结构如下图: 块头记录了如下信息: 块的checksum值 空闲空间的起始位置和结束位置 特殊数据的起始位置 其他一些信息 行指针是一个32bit的数字,具体结构如下: 行内容的偏移量,占15bi

MySQL InnoDB的存储结构总结

从物理意义上来讲,InnoDB表由共享表空间.日志文件组(redo文件组).表结构定义文件组成.若将innodb_file_per_table设置为on,则系统将为每一个表单独的生成一个table_name.ibd的文件,在此文件中,存储与该表相关的数据.索引.表的内部数据字典信息.表结构文件则以.frm结尾,这与存储引擎无关. 以下为InnoDB的表空间结构图: 在InnoDB存储引擎中,默认表空间文件是ibdata1,初始化为10M,且可以扩展,如下图所示: 实际上,InnoDB的表空间文件

ORACLE物理存储结构

1.查看数据库实例基本信息: SQL> SELECT DBID,NAME,CREATED,LOG_MODE,OPEN_MODE,FORCE_LOGGING,CURRENT_SCN,FLASHBACK_ON FROM V$DATABASE; DBID NAME CREATED LOG_MODE OPEN_MODE FORCE_LOGGING CURRENT_SCN FLASHBACK_ON ---------- --------- ----------- ------------ --------

InnoDB存储引擎介绍-(5) Innodb逻辑存储结构

如果创建表时没有显示的定义主键,mysql会按如下方式创建主键: 首先判断表中是否有非空的唯一索引,如果有,则该列为主键. 如果不符合上述条件,存储引擎会自动创建一个6字节大小的指针. 当表中有多个非空的唯一索引,会选择建表时第一个定义的非空唯一索引.注意根据的是定义索引的顺序,不是创建列的顺序. 表空间 tablespace(ibd文件) 段 segment(一个索引2个段) Extent(1MB) Page(16KB) Row Field 表空间