引言

我们都知道,mysql中的索引,事务,锁等都是作为开发人员要重点掌握的知识面,但要想掌握理解好这些知识却并非易事。

其中原因之一就是这些概念都过于抽象,事实上如果都不懂mysql数据是以一种怎样结构存储的,就直接去学习索引等模块,如此理解起来自然是事倍功半的。

因此本文的目的有两点:

  • 揭露数据存储的格式
  • 说明Mysql是如何读取数据

在正文开始之前要先明确一点,Mysql有很多存储引擎,不同的存储引擎对于数据的存放格式是不一样的,目前Mysql的存储引擎默认是InnoDB,因此本文主要以InnoDB的角度去讲解。

行格式

我们经常会说往表中插入一条数据,实际上InnoDB数据存储的基本单位其实就是一条数据。这行数据在磁盘上存储的格式就叫做行格式。

InnoDB设计了4种行格式,分别是Compact、Redundant、Dynamic和Compressed行格式,接下来我们会重点讲解Compact,同时它也是最常用的行格式。

COMPACT行格式

直接先看一张图:

看图说话,Compact行格式可以分为两大块:

  • 额外信息
  • 真实数据

所谓真实数据自然就是我们要存放的值,而额外信息存储的是对这行记录的一些描述。

其中额外信息包括变长字段长度列表,NULL值列表,记录头信息。

变长字段长度列表

在Mysql有一些数据类型,比如VARCHAR(M)、TEXT等,它们是属于支持变长的数据类型,实际使用的字节数是不固定的。所以Mysql需要把这些类型的列实际使用了多少字节数给记录下来,记录的地方就是在变长字段长度列表

在Compact行格式中,把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成一个变长字段长度列表,各变长字段数据占用的字节数按照列的顺序逆序存放。

举个例子,我们创建个表

CREATE TABLE record_format_demo (
-> c1 VARCHAR(10),
-> c2 VARCHAR(10) NOT NULL,
-> c3 CHAR(10),
-> c4 VARCHAR(10)
-> )

可以看到c1,c2,c4列都是变长的,此时我们插入一条数据

INSERT INTO record_format_demo(c1, c2, c3, c4) VALUES('aaaa', 'bbb', 'cc', 'd')

我们假定内容占用的字节为

列名 存储内容 占用字节(十六进制表示)
c1 'aaaa' 0x04
c2 'bbb' 0x03
c4 'd' 0x01

所以这条记录的存储格式就为

可以看到变长字段长度列表是逆序(c4->c2->c1)排放的。

因此要计算1个变长字段到底占用了多少空间要计算两部分:

  • 真实数据占用的空间
  • 记录真实数据占用空间所使用的字节数

以列C1为例:

占用字节数='aaaa'(4字节)+ '0x04'(1字节)

NULL值列表

我们知道表中的某些列可能存储NULL值,如果把这些NULL值都放到记录的真实数据中存储会很占地方,所以Compact行格式把这些值为NULL的列统一管理起来,存储到NULL值列表中。

每个允许存储NULL的列对应一个二进制位,二进制位按照列的顺序逆序排列,,二进制位表示的意义如下:

  • 二进制位的值为1时,代表该列的值为NULL。
  • 二进制位的值为0时,代表该列的值不为NULL。

我们在来插入一条记录

INSERT INTO record_format_demo(c1, c2, c3, c4) VALUES('aaaa', 'bbb', null, null)

因此这条记录的null值列表就是:

行格式就是:

可以看到二进制110就是十进制的6.

记录头信息

记录头信息,它是由固定的5个字节组成。5个字节也就是40个二进制位,不同的位代表不同的意思。本文不会细讲,在后续的文章中有涉及再说讲解。

真实数据

真实数据除了c1、c2、c3、c4这几个我们自己定义的列的数据以外,其实MySQL会为每个记录默认的添加一些列(也称为隐藏列),具体的列如下:

transaction_id和roll_pointer的作用将会在后面提及。

而row_id这个列只有在表没有自定义主键并且Unique键的情况下才会添加,作为表的主键。

以上就是InnoDb存储数据的行格式,下一篇文章将会介绍页的概念。

Mysql综述(1)数据是如何读存的的更多相关文章

  1. Mysql综述--数据是如何读存的?(2)

    页的结构 页是一种InnoDB管理存储空间的基本单位,它一般大小在16kb左右.实际上存在着许多不同类型的页,我们这次主要介绍的页是用来存储数据的,也叫做索引页. 接下来看看索引页的结构图: 比较重要 ...

  2. CentOS6 更改Mysql数据库的数据存放位置

    mysql使用yum安装时,默认的数据是存储在/var/lib/mysql下.一般情况下,为了数据的安全性,建议将mysql数据库的数据文件存储在系统的第二块磁盘上的目录下可以按照以下步骤进行操作: ...

  3. php查询mysql返回大量数据结果集导致内存溢出的解决方法

    web开发中如果遇到php查询mysql返回大量数据导致内存溢出.或者内存不够用的情况那就需要看下MySQL C API的关联,那么究竟是什么导致php查询mysql返回大量数据时内存不够用情况? 答 ...

  4. 大数据学习day33----spark13-----1.两种方式管理偏移量并将偏移量写入redis 2. MySQL事务的测试 3.利用MySQL事务实现数据统计的ExactlyOnce(sql语句中出现相同key时如何进行累加(此处时出现相同的单词))4 将数据写入kafka

    1.两种方式管理偏移量并将偏移量写入redis (1)第一种:rdd的形式 一般是使用这种直连的方式,但其缺点是没法调用一些更加高级的api,如窗口操作.如果想更加精确的控制偏移量,就使用这种方式 代 ...

  5. [转] MySql 优化 大数据优化

    一.我们可以且应该优化什么? 硬件 操作系统/软件库 SQL服务器(设置和查询) 应用编程接口(API) 应用程序 ------------------------------------------ ...

  6. 快速的mysql导入导出数据(load data和outfile)

    1.load data: ***实际应用:把日志生成的xls文件load到MySQL中: mysql_cmd = "iconv -c -f utf-8 -t gbk ./data/al_ve ...

  7. redis作为mysql的缓存服务器(读写分离,通过mysql触发器实现数据同步)

    一.redis简介Redis是一个key-value存储系统.和Memcached类似,为了保证效率,数据都是缓存在内存中.区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录 ...

  8. Ubuntu系统下MySQL读取文件数据ERROR解决

    博文链接:http://haoyuanliu.github.io/2016/04/29/mysql/ 对,我是来骗访问量的!O(∩_∩)O~~ 在使用MySQL进行文件数据读取的时候,在终端敲入命令行 ...

  9. 用python批量向数据库(MySQL)中导入数据

    用python批量向数据库(MySQL)中导入数据 现有数十万条数据,如下的经过打乱处理过的数据进行导入 数据库内部的表格的数据格式如下与下面的表格结构相同 Current database: pyt ...

随机推荐

  1. MongoDB的入门使用以及遇到的坑

    一:MonoDB的简单介绍 MongoDB是一个介于关系型数据库与非关系型数据库中间的数据库,是使用C++进行编写的,他的优点是在支持的查询格式特别的强大,可以进行存储比较复杂的数据类型,支持建立索引 ...

  2. 实战spring自定义属性(schema)

    关于spring自定义属性(schema) 在开发Dubbo应用的时候,我们会在xml中做以下类似的配置: <dubbo:application name="dubbo_service ...

  3. Qt信号槽-原理分析

    目录 一.问题 二.Moc 1.变量 2.Q_OBJECT展开后的函数声明 3.自定义信号 三.connect 四.信号触发 1.直连 2.队列连接 五.总结 六.推荐阅读 一.问题 学习Qt有一段时 ...

  4. vue-cli+webpack打包,上线

    1.先修改配置文件再打包.有些人打包后运行一片空白,主要是由于路径问题 所以首先需要修改config下的index.js配置文件 上图中第一个要修改的就是静态文件的路径,打包后静态文件就在当前目录下, ...

  5. FourAndSix2 靶机渗透

    0x01 简介 FourAndSix2是易受攻击的一个靶机,主要任务是通过入侵进入到目标靶机系统然后提权,并在root目录中并读取flag.tx信息 FourAndSix2.镜像下载地址: https ...

  6. [VB.NET Tips]再谈字符串连接之内置池

    CLR自动维护一个称为"内置池"(暂存池)(intern pool)的表,在编译时此表包含程序中声明的每个唯一的字符串常量的单个实例,以及以编程方式创建的String类的任何唯一实 ...

  7. Hadoop 之 深入探索MapReduce

    1.MapReduce基础概念 答:MapReduce作业时一种大规模数据的并行计算的便程模型.我们可以将HDFS中存储的海量数据,通过MapReduce作业进行计算,得到目标数据. 2.MapRed ...

  8. oracle异机恢复测试

    (一)问题背景 最近在生产环境中,开发人员误操作,使用truncate将oracle数据库某个表的数据全部删除了,在删除之后,开发人员发现自己闯祸了,于是联系值班的DBA进行紧急数据恢复. 经过分析, ...

  9. Spring MVC-从零开始-如何访问静态资源

    转(Spring MVC静态资源处理)   优雅REST风格的资源URL不希望带 .html 或 .do 等后缀.由于早期的Spring MVC不能很好地处理静态资源,所以在web.xml中配置Dis ...

  10. 免费申请 HTTPS 证书,开启全站 HTTPS

    作者:HelloGitHub-追梦人物 文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 HTTP 报文以明文形式传输,如果你的网站只支持 HTTP 协议,那么就有可能遭受到安 ...