1.innodb的存储引擎表类型

如果在创建表时没有显示的定义主键,则innodb存储引擎会按如下方式选择或创建主键

a.首先表中是否有非空的唯一约束(Unique not null)如果有,则该列即为主键

b.不符合上述条件,innodb存储引擎自动创建一个6个字节大小的指针

2.innodb逻辑存储结构

结构和oracle大致相同,所有数据被逻辑的存放在一个空间中,称之为表空间

表空间由 段 区 页 组成,页在一些文档中有时也称为块(block),innodb存储引擎的逻辑存储结构如下图

启用innodb_file_per_table 参数,每张表的表空间内存放的只是数据,索引和插入缓冲

其他数据:撤销信息,系统事务信息、二次写缓冲等还是存在原来的共享表空间内(ibdata1),这也就说明:

即使在启用了参数innodb_file_per_table 之后,共享表空间还是会不断地增加其大小

mysql> show variables like 'innodb_file_per_table'\G;
*************************** 1. row ***************************
Variable_name: innodb_file_per_table
Value: ON
1 row in set (0.05 sec)

ERROR:
No query specified

mysql> system ls -lh /opt/mysql25/data/ib*
-rw-rw----. 1 mysql mysql 76M May 26 21:06 /opt/mysql25/data/ibdata1
-rw-rw----. 1 mysql mysql 48M May 26 21:06 /opt/mysql25/data/ib_logfile0
-rw-rw----. 1 mysql mysql 48M May 26 21:06 /opt/mysql25/data/ib_logfile1
mysql>

共享表空间的大小为76M

mysql> set autocommit=0;

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set (0.00 sec)

mysql> update mytest set name='xianyu' where name='zhuchenghan';
Query OK, 2097152 rows affected (16.97 sec)
Rows matched: 2097152 Changed: 2097152 Warnings: 0

update 后发现ibdata已经增长到了 140MB 这就说明了共享表空间包含undo信息

mysql> system ls -lh /opt/mysql25/data/ib*;
-rw-rw----. 1 mysql mysql 140M May 26 22:21 /opt/mysql25/data/ibdata1
-rw-rw----. 1 mysql mysql 48M May 26 22:21 /opt/mysql25/data/ib_logfile0
-rw-rw----. 1 mysql mysql 48M May 26 22:21 /opt/mysql25/data/ib_logfile1
mysql>

mysql> rollback;
Query OK, 0 rows affected (17.35 sec)

rollback后 大小还是为140M

mysql> system ls -lh /opt/mysql25/data/ib*
-rw-rw----. 1 mysql mysql 140M May 26 22:24 /opt/mysql25/data/ibdata1
-rw-rw----. 1 mysql mysql 48M May 26 22:24 /opt/mysql25/data/ib_logfile0
-rw-rw----. 1 mysql mysql 48M May 26 22:23 /opt/mysql25/data/ib_logfile1

因此很可能的一种情况是再次执行上述的update语句后,会发现ibdata1 不会再增大了

数据段为 B+树的的页节点,索引段为B+树的非索引节点,表空间是由分散的页和段组成

启用参数 Innodb_file_per_table 后 创建的表的大小是96KB,区是64个连续的页,

那创建的表的大小至少是 1MB 才对,其实是因为在每个段开始时,先有32个页大小的碎片页来存放数据,

当这些页使用完之后才是64个连续页的申请

页是innodb磁盘管理的最小单位

数据页

Undo页

系统页

事务数据页

插入缓冲位图页

插入缓冲空闲列表页

未压缩的二进制大对象页

压缩的二进制大对象列

innodb存储引擎是面向行的,也就是说数据库存放按照行进行存放

innodb 的物理结构

从物理意义上来看,innodb表由共享表空间,日志文件组,表结构定义文件组成

若将innodb_file_per_table 设置为ON 则每个表将独立地产生一个表空间文件

以ibd 结尾,数据,索引,表的内部数据字典信息都将保存在独立的表空间中.

表结构以frm结尾,这个与存储引擎无关,任何存储引擎的表结构定义都为.frm文件

innodb行记录格式

记录是以行形式存储.

意味着页中保存着表中一行行的数据.

innodb行格式记录

Compact Redundant

mysql> show table status like 'mytest' \G;
*************************** 1. row ***************************
Name: mytest
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 2092230
Avg_row_length: 40
Data_length: 85573632
Max_data_length: 0
Index_length: 0
Data_free: 7340032
Auto_increment: NULL
Create_time: 2017-05-26 20:48:09
Update_time: NULL
Check_time: NULL
Collation: latin1_swedish_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.01 sec)

数据库实例的一个作用就是读取页中存放的行记录,如果我们知道规则,也可以读取其中的记录

Compact行记录格式

5.0被引入,设计目的是高效存放数据.

Compact 行记录格式如下方式进行存储

Compact格式的 varchar和 char的 null都不占用空间

Redundant 行记录格式

redundant是mysql5.0版本前Innodb的行记录存储方式,是为了向前兼容性

redundant行格式下 的varchar不占用任何存储空间

行溢出数据

Innodb存储引擎可以将一条记录中的某些数据存储在真正的数据页面之外,即作为溢出数据

一般认为BLOB、LOB这类的大对象列类型的存储会把数据存放在数据页面之外

Mysql的varchar数据类型可以存放65535个字节,但是这需要论述

mysql> create table test3 (a varchar(65535)) charset=latin1 engine=innodb;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You hav

从错误消息可以看到,Innodb存储引擎并不支持65535的varchar,因为还有别的开销,因此实际能存放长度为65532

mysql> create table test3 (a varchar(65532)) charset=latin1 engine=innodb;
Query OK, 0 rows affected (0.11 sec)

如果做上述例子的时候并没有将sql_mode设置为严格模式,则可能会出现可以建立表,但是会有警告信息

警告信息提示了 之所以可以创建是因为mysql自动将varchar转换成了TEXT 类型.如果我们看test的表结构,

会发现mysql自动将varchar类型转换成了MEDIUTEX 类型

需要注意的是上述创建varchar长度为65535的表其实是 latin1 的如果换成GBK 或utf8会怎么样

这次即使创建65532也会报错,但是两次报错对于max值的提示是不同的,因此我们应该理解varchar(N)中,N指的是字符的长度,

varchar类型最大支持65535指的是65535 个字节

此外,mysql官方手册中定义的65535长度是指VARCHAR列的长度总和,

如果列的长度总和超出这个长度,依然无法创建

3个列长度总和是66000,因此Innodb 存储引擎再次报了同样的错误,即使我们能存放65532个字节了,但是INNODB 存储引擎的页为16KB

即16384 个字节,怎么能存放65532个字节呢?

一般情况数据都存储在 B-TREE Node 的页类型中,但是当发生溢出时,则这个存放行溢出的页类型为 Uncompress BLOB Page

mysql> create table t3(a varchar(65532));
Query OK, 0 rows affected (0.04 sec)

mysql>
mysql> insert into t3 select repeat('a',65532);
Query OK, 1 row affected (0.09 sec)
Records: 1 Duplicates: 0 Warnings: 0

可以看到一个B-tree Node页类型,另外4个为Uncompressed BLOB Page

这些页中才真正存放了65532个字节的数据,既然实际存放的数据都放到BLOB中,数据页放的什么呢

通过hexdump来读取表空间文件

.......

可以看到,对于行溢出数据,存储方式如下

mysql> create table t4 (a varchar(9000));
Query OK, 0 rows affected (0.06 sec)

mysql>
mysql>
mysql> insert into t4 select repeat('a',9000);
Query OK, 1 row affected (0.01 sec)
Records: 1 Duplicates: 0 Warnings: 0

但是如果可以在一个页中至少放入两行的数据,那varchar就不会放到blob页中

这个阀值的长度为8098

innodb 表的更多相关文章

  1. MySQL InnoDB表--BTree基本数据结构

    MySQL InnoDB表是索引组织表这一点应该是每一个学习MySQL的人都会首先学到的知识,这代表这表中的数据是按照主键顺序存储,也就是说BTree的叶子节点存储了所有该行的数据. 我最开始是搞Or ...

  2. Innodb 表空间传输迁移数据

    在mysql5.5之前,mysql实例中innodb引擎表的迁移是个头疼的问题,要么使用mysqldump导出,要么使用物理备份的方法,但是在mysql5.6之后的版本中,可以使用一个新特性,方便地迁 ...

  3. [MySQL FAQ]系列 — 为什么InnoDB表要建议用自增列做主键

    我们先了解下InnoDB引擎表的一些关键特征: InnoDB引擎表是基于B+树的索引组织表(IOT): 每个表都需要有一个聚集索引(clustered index): 所有的行记录都存储在B+树的叶子 ...

  4. Innodb 表空间卸载、迁移、装载

    从MySQL的Innodb特性中我们知道,Inndob的表空间有共享和独享的特点,如果是共享的.则默认会把表空间存放在一个文件中(ibdata1),当开启独享表空间参数Innodb_file_per_ ...

  5. Innodb之拷贝InnoDB表从一服务器到另一台服务器2

    本章节阐述将表移动到不同server上的技术.如可以将整个Mysql 实例转移到更大.更快的Server上:也可以拷贝整个实例到Slave上:也可以拷贝单个表或某些表到其他Server上(数据仓库). ...

  6. Innodb 表修复(转)

    摘要:      突然收到MySQL报警,从库的数据库挂了,一直在不停的重启,打开错误日志,发现有张表坏了.innodb表损坏不能通过repair table 等修复myisam的命令操作.现在记录下 ...

  7. 14.8.4 Moving or Copying InnoDB Tables to Another Machine 移动或者拷贝 InnoDB 表到另外机器

    14.8.4 Moving or Copying InnoDB Tables to Another Machine 移动或者拷贝 InnoDB 表到另外机器 这个章节描述技术关于移动或者复制一些或者所 ...

  8. 14.8.3 Physical Row Structure of InnoDB Tables InnoDB 表的物理行结构

    14.8.3 Physical Row Structure of InnoDB Tables InnoDB 表的物理行结构 一个InnoDB 表的物理行结构取决于在创建表指定的行格式 默认, Inno ...

  9. 14.8.2 Role of the .frm File for InnoDB Tables InnoDB 表得到 .frm文件的作用

    14.8.2 Role of the .frm File for InnoDB Tables InnoDB 表得到 .frm文件的作用 Vsftp:/data01/mysql/zjzc# ls -lt ...

  10. 14.8.1 Creating InnoDB Tables 创建InnoDB 表

    14.8.1 Creating InnoDB Tables 创建InnoDB 表 创建一个InnoDB表,使用CREATE TABLE 语句,你不需要指定ENGINE=InnoDB 子句 如果Inno ...

随机推荐

  1. 【Java多线程系列六】Map实现类

    Map的一些实现类有及其特性 类 线程安全 特性 Hashtable 是 Key不能为null HashMap 否 读写效率最高,但在Java6多线程环境下使用不当可能陷入死循环,进而导致CPU使用率 ...

  2. 天道神诀--IPSAN实现多链路以及多路径安装

    # linux6 环境需求 ISCSI服务端: 2张网卡,足够的磁盘空间 iscsi客户端: 2张网卡(与服务端网段相同) ISCSI服务端配置: 与1张网卡配置主要差别在于配置文件中的允许访问网段, ...

  3. pytest--fixture之参数化

    场景:测试用例执行时,有的用例需要登陆才能执行,有些用例 不需要登陆.setup和teardown无法满足.fixture可以.默认 scope(范围)function • 步骤: 1. 导入pyte ...

  4. IPointCollection.AddPoint Method的用法

    补充指出官方帮助的一个问题. 该方法用于向环.线.面等几何中添加节点.官方帮助里是这样描述的:Adds a vertex to a Path, Ring, Polyline, or Polygon; ...

  5. kubeadm生成的token重新获取

    当你的token忘了或者过期,解决办法如下: 1.先获取token #如果过期可先执行此命令kubeadm token create #重新生成token#列出tokenkubeadm token l ...

  6. PHP 类中静态方法调用非静态方法

    静态方法调用非静态方法: 在类中静态方法中,需要实例化对象,然后再调用类中的方法 非静态方法调用静态方法: 可以self 或者 类名加::的形式调用 如下面的案例: <?php class A{ ...

  7. typescript + vue开发遇到的坑

    1,错误 :TS2304: Cannot find name 'require' 在ts使用nodejs,没有安装nodejs的TypeScript定义类型 ,使用require报的错 解决方法:如果 ...

  8. Download Kali Linux

    https://www.kali.org/downloads/

  9. Struts2配置详情

    Struts2的核心功能是action,对于开发人员来说,使用Struts2主要就是编写action,action类通常都要实现com.opensymphony.xwork2.Action接口,并实现 ...

  10. 阿里云HBase推出全新X-Pack服务 定义HBase云服务新标准

    2018年12月13日,第八届中国云计算标准和应用大会在京召开,会上阿里云HBase宣布推出全新X-Pack服务,支持SQL.时序.时空.图.全文检索能力.复杂分析,从处理到分析全栈式数据库,客户开箱 ...