从概念上讲大多数关系数据库系统是相似的它们有一系列数据库组成每个数据库包含一系列数据库表但每个系统有各自组织其管理的数据方式MySQL也不例外
缺省地所有由MySQL服务器mysqld管理的数据存储在一个称为MySQL数据目录的地方所有数据库都存放在哪儿也包括提供服务器操作信息的状态文件如果你对一个MySQl安装执行管理任务你应该熟知数据目录的布局及用途
本文介绍下列专题
如何确定数据目录的位置
服务器如何组织并提供对数据库和它管理的表的访问
在哪里找到由服务器生成的状态文件记忆它们包含什么内容
如何改变缺省地点或数据目录或单独数据库的组织结构
数据目录的位置
一个缺省数据目录被编译进了服务器如果你从一个源代码分发安装MySQL典型的缺省目录为/usr/local/var如果从RPM文件安装则为/var/lib/mysql如果从一个二进制分发安装则是/usr/local/mysql/data
在你启动服务器通过使用一个datadir=/path/to/dir选项可以明确指定数据目录位置如果你想把数据目录置于其它缺省位置外的某处这很有用
作为一名MySQL管理员你应该知道你的数据目录在哪里如果你运行多个服务器你应该是到所有数据目录在哪里但是如果你不知道确切的位置由多种方法找到它
使用mysqladmin variables从你的服务器直接获得数据目录路径名查找datadir变量的值在Unix上其输出类似于
%mysqladmin variables
+++
| variable_name | Value |
+++
| back_log | |
| connect_timeout | |
| basedir | /var/local/ |
| datadir | /usr/local/var/ |
在Windows上输出可能看上去像这样
c:mysqladmin variables
+++
| variable_name | Value |
+++
| back_log | |
| connect_timeout | |
| basedir | c:mysql |
| datadir | c:mysqldata |
如果你有多个服务器在运行它们将在不同的TCP/IP端口或套接字上监听通过提供连接服务器正在监听的端口或套接字的port或socket选项你可以轮流获得它们每一个的数据目录信息
%msqladmin port=port_name variables
%mysqladmin socket=/path/to/socket variables
mysqladmin命令可运行在任何你能从其连接服务器的主机上如果你想在一个远程主机连接服务器使用一个host=host_name选项
%mysqladmin host=host_name variables
在Windows上你可以通过使用pipe强制一个命令管道连接和socket=pipe_name指定管道名来连接监听一个命令管道的NT服务器
c:mysqladmin pipe socket=pipe_name variables
你可以使用ps命令查看任何正在运行mysqld 进程的命令行
试一下下列命令之一并寻找datadir
%ps axww | grep mysql BSD风格
%ps ef | grep mysqld System V风格
如果你的系统运行多个服务器ps命令可能特别有用因为你能马上发现多个数据目录位置缺点是必须在服务器上运行而且可能没有有用的信息产生除非在mysqld命令行上明确指定了datadir选项
如果MySQL是从一个源代码分发安装的你可以检查其配置信息确定数据目录位置例如位置可从顶级Makefile中获得但是注意位置是Makefile中的localstatedir值不是datadir而且如果分发位于一个NFS挂载的文件系统并用来为多个主机构建MySQL配置信息反映了分发被最新构建的主机这可能不能提供你感兴趣的主机的数据目录信息
如果上述方式失败你可以用find寻找数据库文件下列命令寻找frm文件它是任何MySQL安装的一部分
% find / name frm print
在下文各例中用DATADIR表示MySQL数据目录位置
数据目录结构
MySQL数据目录包含了服务器管理的所有数据目录这些文件被组织成一个树状结构通过利用Unix或Windows文件系统的层次结构直接实现
每个数据库对应于数据目录下的一个目录
在一个数据库中的表对应于数据目录下的文件
数据目录也包含由服务器产生的几个状态文件如日志文件这些文件提供了关于服务器操作的重要信息对管理特别在出了问题而试图确定问题原因时很有价值例如如果某个特定查询杀死服务器你可以通过检查日志文件判别捣乱的查询
MySQL服务器怎样提供对数据的访问
在数据目录下的一切由一个单独的实体MySQL服务器mysqld管理客户程序绝不直接操作数据相反服务器提供数据可访问的切入点它是客户程序与它们想使用的数据之间的中介
当服务器启动时如果有需要它打开日志文件然后通过监听网络连接位数据目录呈现一个网络接口要访问数据客户程序建立对服务器的一个连接然后以MySQL查询传输请求来执行希望的操作服务器执行每一个操作并将结果发回用户服务器是多线程的并能服务多个同时的客户连接然而因为修改操作一个执行一个实际效果是顺序化请求以使两个客户决不能在同一时刻改变同一记录
在正常的情况下让服务器作为数据库访问的唯一仲裁者提供了避免可从同时访问数据库表的多个进程的破坏的保证管理员应该知道有时服务器没有对数据目录的独裁控制
当你在一个单个数据目录上运行多个服务器一般倪云新一个服务器管理主机上的所有数据库但是有可能运行多个服务器如果这完成提供对多个独立数据目录的访问没有相互影响的问题但哟也能启动多个服务器并指向同一个目录一般地这不是一个好主意如果你试图这样最好是你的系统提供良好的文件锁定功能否则服务器将不能正确协作如果你将多个服务器同时写入日志文件你也冒着你的日志文件称为混乱的根源的风险
在你运行isamchk和myisamchk时isamchk和myisamchk实用程序用于表的维护诊错和修复就想你想的那样因为这些程序可以修改表内容允许它们与服务器正在操作的同时对表操作这样能导致表损坏理解如何限制这种相互影响是很重要的这样你不会损坏你的表
数据目表示
每个MySQL服务器管理的数据库有自己的数据库表它是数据目录下的一个子目录其名字与它表示的数据库相同例如数据库my_db对应于数据库目录DATADIR/my_db
这种表示允许多个数据库级的语句在其实现中十分简单CREATE DATABASE db_name在数据目录中创建一个db_name空目录具有只允许MySQL服务器用户(运行服务器的Unix用户)的属主和模式这等价于下列手工在服务器主机上创建数据库
%mkdir DATADIR/db_name
%chmod DADADIR/db_name
用一个空目录表示一个新数据库的最简单方法与其它数据库甚至为一个空数据库创建大量的控制文件或系统文件正好相反
DROP DATABASE语句实现同样简单DROP DATABASE db_name删除数据库中的db_name目录和所有表文件这几乎与下列命令一样
%rm rf DATADIR/db_name
(差别是服务器只删除具有已知用于表的后缀名的文件如果你在数据库目录创建了其它文件则服务器保留它们而且目录本身不被删除
SHOW DATABASE基本上不做什么只是列出位于数据目录中的目录名有些数据库系统保持一个主表用于维护所有数据库但在MySQL无此构件由于赋予数据目录结构的简洁性数据库列表隐含在数据目录的内容中而且这样的表不必有额外的开销
数据库表的表示
每个数据库在数据库目录中有个文件一个样式(描述文件)一个数据文件和一个索引文件每个文件的基本名是表名文件名扩展名代表文件类型扩展名如下表数据和索引文件的扩展名指出表使用老式IASM索引或新式MyISAM索引
表 MySQL文件类型
文件类型 文件名扩展名 文件内容
样式文件 frm 描述表的结构(它的列列类型索引等)
数据文件 ISD(ISAM)
或MYD(MyISAM) 包含数据文件上的所有索引的索引树
索引文件 ISM(ISAM)
或MYI(MyISAM) 该索引文件依赖表是否有索引而存在
当你发出一条CREATE TABLE tbl_name时语句定义表的结构时服务器创建一个名为tbl_namefrm的文件它包括该结构的内部编码同时也创建一个空数据和索引文件初始化为包含指出无记录和无索引的信息(如果CREATE TABLE语句包括索引指定索引文件反映出这些索引)对应于表的文件的属主和模式被设置为只允许MySQL服务器用户访问
当你发出一条ALTER TABLE tbl_name语句时服务器重新编码tbl_namefrm并修改数据和索引文件的内容以反映语句指定的结构改变对于CREATE INDEX和DROP INDEX也是一样因为它们被服务器视为与ALTER TABLE等价DROP TABLE通过删除对应于表的三个文件来实现
虽然你可以通过删除数据库目录中对应于表的三个文件但不能手工创建或修改一个表如如果my_db是当前数据库DROP TABLE my_tbl大概等价于下列命令