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. HBase 永久RIT(Region-In-Transition)问题

    HBase 永久RIT(Region-In-Transition)问题:异常关机导致HBase表损坏和丢失,大量Regions 处于Offline状态,无法上线. 问题1:启动HBase时,HBase ...

  2. 令人清爽的异步函数async、await

    1.什么是async.await? async用于声明一个函数是异步的.而await从字面意思上是"等待"的意思,就是用于等待异步完成.并且await只能在async函数中使用; ...

  3. transport error 202: bind failed: Address already in use

    background: I have terminated some test debugger without properly saying goodbye. the JDWP didn't cl ...

  4. 关于EntityFramework 更新数据记录时字段全部更新问题和不从数据库中获取直接更新记录

    一.一直对这个比较疑惑感觉只修改一条数据记录的一个字段结果更新Savechages后跟踪生成sql竟然是全部被修改,感觉微软怎么这么傻,总觉得会有其它方式可以只更新部分字段,但一直没有找到相关设置,最 ...

  5. 10_PAE_非PAE

    前置知识: 在 windows 中 保护模式 有两种模式: 段保护 和 页保护 段保护 主要体现在 段选择子上:但是数据段.代码段.栈段等采用的都是4GB平坦模式,段的特征并没有那样展现.所以具体的保 ...

  6. http11.Http11OutputBuffer.SocketOutputBuffer.doWrite

    这是一个错误. 我在spring框架中,创建了一个基类SuperBaseController, 并且使用了@ModelAttribute用来给HttpServletRequest和HttpServle ...

  7. leetcood学习笔记-206-反转链表

    题目描述: 最佳解: class Solution(object): def reverseList(self, head): """ :type head: ListN ...

  8. Nginx的动静分离

    Nginx的动静分离 在之前我们的负载均衡中,我们再jsp中设置了一个背景,这是一个静态资源,Tomcat处理静态资源的效率并没有Nginx高,我们可以通过动静分离将静态资源和动态资源分割开来,Tom ...

  9. Django 查漏补缺

    Django 查漏补缺 Django  内容回顾: 一. Http 请求本质: 网络传输,运用socket Django程序: socket 服务端 a. 服务端监听IP和端口 b. 浏览器发送请求 ...

  10. 绘制delphi窗体的标题栏

    绘制delphi窗体的标题栏 按照设计,Delphi窗体的“标题”属性是由Windows负责绘制,标题栏在系统菜单旁边.如果你不想改变窗体的标题属性又想在窗体的标题栏添加一些自己的内容,你需要处理一个 ...