图说:InnoDB之表空间

InnoDB是MySQL的重要存储引擎,为数据提供了很好的稳定性。一方面,它借鉴了很多ORACLE特性,另一方面InnoDB也有很多自己的特点诸如Insert buffering、Double write等[2]。了解InnoDB的内部机制,可以帮助我们更好的配置和优化它。本文概述了InnoDB的表空间的结构,算是深入了解的第一步。上图先:

TableSpaceInnoDB

  1. 在配置文件中可以配置InnoDB的表空间[1],一般格式如下(共享表空间):
    datadir = /opt/mysql/data
    innodb_data_file_path=ibdata1:1G;ibdata2:1G;ibdata3:1G;ibdata4:1G;ibdata5:1G
  2. 完整的表空间,会被分成如下结构供给InnoDB使用。最小单位是page,每个page为16K;64个连续的page组成一个extent;多个extent和page构成一个segment。Segment初始时InnoDB会为它分配32个pages,之后根据需要会将extent分配给segment,单次最多会分配4个extends给segment。[1]
  3. 具体的,InnoDB中一个索引(B-tree)由两个segment组成。其中,所有的叶子节点(leaf nodes)存放在一个segment中,所有的非叶子节点(nonleaf nodes)存放在一个segment中。[1]
  4. 一个存放记录(row)的page,由page header、page trailer、page body组成。如下图:[2]
    page_with_rows
  5. 相关的InnoDB的参数:innodb_data_file_path。

参考文献:

  1. http://dev.mysql.com/doc/refman/5.0/en/innodb-file-space.html
  2. InnoDB Internals: InnoDB File Formats and Source Code Structure,MySQL Conference, April 2009, Heikki Tuuri CEO Innobase, Calvin Sun Principal Engineer, Oracle Corporation

In:

8 responses to “图说:InnoDB之表空间”

  1. 玄月

    第一点说明中,是共享表空间。
    独享表空间是要设置innodb_file_per_table=1

  2. 3KS 弄错了 已经改过了

  3. […] 当事务(Transaction)需要修改某条记录(row)时,InnoDB需要将该数据所在的page从disk读到buffer pool中,事务提交后,InnoDB修改page中的记录(row)。这时buffer pool中的page就已经和disk中的不一样了,我们称buffer pool中的page为dirty page。Dirty page等待flush到disk上。 […]

  4. […] 在InnoDB中,是以16K的页(Page)为基本的存储单位的。我们知道,InnoDB是的数据是在Clustered index中存储的,在Secondary index中仅存储对应数据的PK。Clustered index和Secondary index都是B-Tree结构的,所以对InnoDB数据页和索引页的压缩很大程度上就是对B-Tree节点页的压缩。 […]

  5. […] 当事务(Transaction)需要修改某条记录(row)时,InnoDB需要将该数据所在的page从disk读到buffer pool中,事务提交后,InnoDB修改page中的记录(row)。这时buffer pool中的page就已经和disk中的不一样了,我们称buffer pool中的page为dirty page。Dirty page等待flush到disk上。 […]

  6. […] 当事务(Transaction)需要修改某条记录(row)时,InnoDB需要将该数据所在的page从disk读到buffer pool中,事务提交后,InnoDB修改page中的记录(row)。这时buffer pool中的page就已经和disk中的不一样了,我们称buffer pool中的page为dirty page。Dirty page等待flush到disk上。 […]

  7. seven

    有个疑问,一直不是很清楚,想问一下您,InnoDB表t1: (id,a,b,c,d,e,f,g,h)

    primary key为id,为聚簇索引

    secondary key 有两个,一个为key_ab(a,b) 实际上(a,b,id),另一个为key_c(c)实际上是(c,id)

    按照一个索引有两个segment的说法,是不是应该有6个segment,结构如下:

    key_ab的segment:nonleaf nodes segment中放置是(a,b) ,leaf nodes segment放置是 (id)

    key_c的segment: nonleaf nodes segment 中放置的是(c),leaf nodes segment放置的是(id)

    聚簇索引也就是primary key组织的数据:nonleaf nodes segment中放置的是(id), leaf nodes segment放置的是(id,a,b,c,d,e,f,g,h)

    如果我select a,b from t1,覆盖索引扫描, 那么是不是从InnoDB表空间中,查到key_ab的两个segment中的nonleaf nodes segment中直接查询数据?

    如果select * from t1 的话是不是直接从聚簇索引中的leaf nodes segment取数据呢?

Leave a Reply

Your email address will not be published. Required fields are marked *