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

最新文章

  1. jQuery Scroll Follow
  2. nginx-my
  3. android 设置textview跑马灯效果
  4. (转)轻松学习JavaScript三:JavaScript与HTML的结合
  5. [知识点]计算几何I——基础知识与多边形面积
  6. JavaSE复习_8 泛型程序设计
  7. 【Python】代码行数统计
  8. FlexSlider是一个非常出色的jQuery滑动切换插件
  9. background-size使用
  10. cocos2d-x 截取屏幕可见区域
  11. 写了交互给后台后来不能用?bug多多多又找不到文件效率低?工作流程帮你优化起来~~~~
  12. 字符串:"2016-09-21T18:57:50+08:00[Asia/Chungking]" 转Date
  13. 201521123032 《Java程序设计》第12周学习总结
  14. 百度地图API显示多个标注点带百度样式信息检索窗口的代码
  15. 2.3Options建立配置和实体的映射「深入浅出ASP.NET Core系列」
  16. 一、Spring Boot 入门
  17. “<textarea>”内的文字对齐
  18. LeetCode(90):子集 II
  19. django之模型层(model)--查询补充及cookie
  20. Selenium和firefox兼容性问题

热门文章

  1. 【node】---token的原理及使用---【alley】
  2. laydate box-sizingCSS就会变形
  3. 统计HDFS 上字节数据统计
  4. [已解决]报错SyntaxError: Non-ASCII character '\xe6'
  5. linux下读取移动硬盘
  6. 使用Postman模拟HTTP请求
  7. Pregel Combiner
  8. 压缩与解压缩 gzip bzip2 tar 命令
  9. PHP - 实现 strStr()
  10. laravel passport client_credentials