天天看点

MySQL基础 - MySQL的数据目录

把总结写开头:

明天再写吧,上床睡觉。

一、数据库和文件系统的关系

innodb 、 myisam 这样的存储引擎都是把表存储在文件系统上的。当我们想读取数据的时候,这些存储引擎会从文件系统中把数据读出来返回给我们,当我们想写入数据的时候,这些存储引擎会把这些数据又写回文件系统。

二、mysql数据目录

mysql服务器程序在启动时会到文件系统的某个目录下加载一些文件,之后在运行过程中产生的数据也都会存储到这个目录下的某些文件中,这个目录就称为<code>数据目录</code>。

<code>mysql</code>的安装目录(在安装<code>mysql</code>的时候我们可以自己指定),我们重点强调过这个<code>安装目录</code>下非常重要的<code>bin</code>目录,它里边存储了许多关于控制客户端程序和服务器程序的命令(许多可执行文件,比如<code>mysql</code>,<code>mysqld</code>,<code>mysqld_safe</code>等等等等好几十个)。

而<code>数据目录</code>是用来存储<code>mysql</code>在运行过程中产生的数据,一定要和本章要讨论的<code>安装目录</code>区别开!一定要区分开!一定要区分开!一定要区分开!

那说了半天,到底<code>mysql</code>把数据都存到哪个路径下呢?其实<code>数据目录</code>对应着一个系统变量<code>datadir</code>,我们在使用客户端与服务器建立连接之后查看这个系统变量的值就可以了:

从结果中可以看出,在我的计算机上<code>mysql</code>的数据目录就是<code>/usr/local/var/mysql/</code>

三、数据目录的结构

<code>mysql</code>在运行过程中都会产生哪些数据呢?当然会包含我们创建的数据库、表、视图和触发器吧啦吧啦的用户数据,除了这些用户数据,为了程序更好的运行,<code>mysql</code>也会创建一些其他的额外数据,我们接下来细细的品味一下这个<code>数据目录</code>下的内容。

每当我们使用<code>create database 数据库名</code>语句创建一个数据库的时候,在文件系统上实际发生了什么呢?其实很简单,每个数据库都对应数据目录下的一个子目录,或者说对应一个文件夹,我们每当我们新建一个数据库时,<code>mysql</code>会帮我们做这两件事儿:

在<code>数据目录</code>下创建一个和数据库名同名的子目录(或者说是文件夹)。

在该与数据库名同名的子目录下创建一个名为<code>db.opt</code>的文件,这个文件中包含了该数据库的各种属性,比方说该数据库的字符集和比较规则是个啥。

比方说我们查看一下在我的计算机上当前有哪些数据库:

可以看到在我的计算机上当前有7个数据库,其中<code>charset_demo_db</code>、<code>dahaizi</code>和<code>xiaohaizi</code>数据库是我们自定义的,其余4个数据库是属于mysql自带的系统数据库。我们再看一下我的计算机上的<code>数据目录</code>下的内容:

当然这个数据目录下的文件和子目录比较多哈,但是如果仔细看的话,除了<code>information_schema</code>这个系统数据库外,其他的数据库在<code>数据目录</code>下都有对应的子目录。这个<code>information_schema</code>比较特殊。

我们的数据其实都是以记录的形式插入到表中的,每个表的信息其实可以分为两种:

表结构的定义

表中的数据

<code>表结构</code>就是该表的名称是啥,表里边有多少列,每个列的数据类型是啥,有啥约束条件和索引,用的是啥字符集和比较规则吧啦吧啦的各种信息,这些信息都体现在了我们的建表语句中了。为了保存这些信息,<code>innodb</code>和<code>myisam</code>这两种存储引擎都在<code>数据目录</code>下对应的数据库子目录下创建了一个专门用于描述表结构的文件,文件名是这样:

比方说我们在<code>dahaizi</code>数据库下创建一个名为<code>test</code>的表:

那在数据库<code>dahaizi</code>对应的子目录下就会创建一个名为<code>test.frm</code>的用于描述表结构的文件。值得注意的是,这个后缀名为.frm是以二进制格式存储的

前边重点唠叨过<code>innodb</code>的一些实现原理,到现在为止我们应该熟悉下边这些东东:

<code>innodb</code>其实是使用<code>页</code>为基本单位来管理存储空间的,默认的<code>页</code>大小为<code>16kb</code>。

对于<code>innodb</code>存储引擎来说,每个索引都对应着一棵<code>b+</code>树,该<code>b+</code>树的每个节点都是一个数据页,数据页之间不必要是物理连续的,因为数据页之间有<code>双向链表</code>来维护着这些页的顺序。

<code>innodb</code>的聚簇索引的叶子节点存储了完整的用户记录,也就是所谓的索引即数据,数据即索引。

为了更好的管理这些页,设计<code>innodb</code>的大叔们提出了一个<code>表空间</code>或者<code>文件空间</code>(英文名:<code>table space</code>或者<code>file space</code>)的概念,这个表空间是一个抽象的概念,它可以对应文件系统上一个或多个真实文件(不同表空间对应的文件数量可能不同)。每一个<code>表空间</code>可以被划分为很多很多很多个<code>页</code>,我们的表数据就存放在某个<code>表空间</code>下的某些页里。设计<code>innodb</code>的大叔将表空间划分为几种不同的类型,我们一个一个看一下。

这个所谓的<code>系统表空间</code>可以对应文件系统上一个或多个实际的文件,默认情况下,<code>innodb</code>会在<code>数据目录</code>下创建一个名为<code>ibdata1</code>(在你的数据目录下找找看有木有)、大小为<code>12m</code>的文件,这个文件就是对应的<code>系统表空间</code>在文件系统上的表示。怎么才<code>12m</code>?这么点儿还没插多少数据就用完了,哈哈,那是因为这个文件是所谓的<code>自扩展文件</code>,也就是当不够用的时候它会自己增加文件大小~

当然,如果你想让系统表空间对应文件系统上多个实际文件,或者仅仅觉得原来的<code>ibdata1</code>这个文件名难听,那可以在<code>mysql</code>启动时配置对应的文件路径以及它们的大小,比如我们这样修改一下配置文件:

这样在<code>mysql</code>启动之后就会创建这两个512m大小的文件作为<code>系统表空间</code>,其中的<code>autoextend</code>表明这两个文件如果不够用会自动扩展<code>data2</code>文件的大小。

在一个mysql服务器中,系统表空间只有一份

在mysql5.6.6以及之后的版本中,<code>innodb</code>并不会默认的把各个表的数据存储到系统表空间中,而是为每一个表建立一个独立表空间,也就是说我们创建了多少个表,就有多少个独立表空间。使用<code>独立表空间</code>来存储表数据的话,会在该表所属数据库对应的子目录下创建一个表示该<code>独立表空间</code>的文件,文件名和表名相同,只不过添加了一个<code>.ibd</code>的扩展名而已,所以完整的文件名称长这样:

比方说假如我们使用了<code>独立表空间</code>去存储<code>xiaohaizi</code>数据库下的<code>test</code>表的话,那么在该表所在数据库对应的<code>xiaohaizi</code>目录下会为<code>test</code>表创建这两个文件:

其中<code>test.ibd</code>文件就用来存储<code>test</code>表中的数据和索引。当然我们也可以自己指定使用<code>系统表空间</code>还是<code>独立表空间</code>来存储数据,这个功能由启动参数<code>innodb_file_per_table</code>控制,比如说我们想刻意将表数据都存储到<code>系统表空间</code>时,可以在启动<code>mysql</code>服务器的时候这样配置:

当<code>innodb_file_per_table</code>的值为<code>0</code>时,代表使用系统表空间;当<code>innodb_file_per_table</code>的值为<code>1</code>时,代表使用独立表空间。不过<code>innodb_file_per_table</code>参数只对新建的表起作用,对于已经分配了表空间的表并不起作用。如果我们想把已经存在系统表空间中的表转移到独立表空间,可以使用下边的语法:

或者把已经存在独立表空间的表转移到系统表空间,可以使用下边的语法:

其中中括号扩起来的<code>=</code>可有可无,比方说我们想把<code>test</code>表从独立表空间移动到系统表空间,可以这么写:

随着mysql的发展,除了上述两种老牌表空间之外,现在还新提出了一些不同类型的表空间,比如通用表空间(general tablespace)、undo表空间(undo tablespace)、临时表空间(temporary tablespace)吧啦吧啦的,具体情况我们就不细唠叨了,等用到的时候再提。

nice to see you all!