MyISAM 存储引擎
mysql
MyISAM 基于旧的 (再也不可用) ISAM 存储引擎, 但有许多有用的扩展。sql
每一个 MyISAM 表都存储在三个文件中的磁盘上。这些文件具备以表名开头的名称, 并具备用于指示文件类型的扩展名。数据库
.frm文件存储表定义。缓存
数据文件的扩展名为.MYD (MYData)。安全
索引文件的扩展名是.MYI (MYIndex)服务器
要明确表示要用一个MyISAM表格,请用ENGINE表选项指出来:架构
CREATE TABLE t (i INT) ENGINE = MYISAM;并发
在 MySQL 5.7 中, 一般须要使用 ENGINE 来指定 MyISAM 存储引擎, 由于 InnoDB 是默认引擎。ide
可使用 mysqlcheck 客户端或 myisamchk 实用程序检查或修复 MyISAM 表。还可使用 myisampack 压缩 MyISAM 表, 以减小更少的空间。工具
以下是MyISAM存储引擎的一些特征:
1. 全部数据值首先以低字节存储。这使得数据机器和操做系统独立。二进制可移植性的惟一要求是机器使用两个补间符号整数和 IEEE 浮点格式。这些要求普遍应用于在主流机器中。二进制兼容性可能不适用于有特殊的处理器的嵌入式系统。
2. 先存储数据低字节并不严重地影响速度;数据行中的字节通常是未联合的,从一个方向读未联合的字节并不比从反向读更占用更多的资源。服务器上的获取列值的代码与其它代码相比并不显得时间紧。
3. 全部数字键值以高字节为先被存储以容许一个更高地索引压缩
4. 大文件(达63位文件长度)在支持大文件的文件系统和操做系统上被支持
5. MyISAM表最大行数为 18440000000000000000
6. 每一个MyISAM表最大索引数是64
7. 每一个索引最大的列数是16个
8. 最大的键长度是1000字节。这也能够经过编译来改变。对于键长度超过250字节的状况,一个超过1024字节的的键块被用上。
9. 当记录以排好序的顺序插入(就像你使用一个AUTO_INCREMENT列之时),索引树被劈开以便高节点仅包含一个键。这改善了索引树的空间利用率。
10. 支持每表一个AUTO_INCREMEN列的内部处理。MyISAM为INSERT和UPDATE操做自动更新这一列。这使得AUTO_INCREMENT列更快(至少10%)。在序列顶的值被删除以后就不能再利用。(当AUTO_INCREMENT列被定义为多列索引的最后一列,能够出现重使用从序列顶部删除的值的状况 )。AUTO_INCREMENT值可用ALTER TABLE或myisamch来重置。
11. 当把删除和更新及插入混合的时候,动态尺寸的行更少碎片。这要经过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块来自动完成。
12. MyISAM 支持并发插入:若是数据文件中间的表没有自由块了,在其它线程从表读的同时,你能够INSERT新行到表中。(这被认识为并发操做 )。自由块的出现是做为删除行的结果,或者是用比当前内容多的数据对动态长度行更新的结果。当全部自由块被用完(填满),将来的插入又变成并发。请参阅8.11.3 节 "并发插入"。
13. 你能够把数据文件和索引文件放在不一样目录,用DATA DIRECTORY和INDEX DIRECTORY选项CREATE TABLE以得到更高的速度,请参阅13.3.18节,“CREATE TABLE语法”。
14. BLOB和TEXT列能够被索引。
15. NULL值被容许在索引的列中。这个占每一个键的0-1个字节
16. 每一个字符列能够又不一样的字符集,请参阅第10.1章 :“字符集支持”。
17. 在MyISAM索引文件里又一个标志,它代表表是否被正确关闭。若是用--myisam-recover选项启动mysqld,MyISAM表在打开得时候被自动检查,若是被表被不恰当地关闭,就修复表。
18. 若是你用--update-state选项运行myisamchk,它标注表为已检查。myisamchk --fast只检查那些没有这个标志的表。
19. myisamchk --analyze为部分键存储统计信息,也为整个键存储统计信息。
20. myisampack能够打包BLOB和VARCHAR列
MyISAM也支持下列特征:
1. 支持true VARCHAR类型;VARCHAR列以存储在2个字节中的长度来开始。
2. 有VARCHAR的表能够有固定或动态记录长度。
3. VARCHAR和CHAR列能够多达64KB。
4. 一个被搞乱的已计算索引对可对UNIQUE来使用。这容许你在表内任何列的合并上有UNIQUE。(尽管如此,你不能在一个UNIQUE已计算索引上搜索)。
MyISAM 启动选项:
mysqld 的如下选项可用于更改 MyISAM 表的行为。有关其余信息, 请参见5.1.4 节 "服务器命令选项"。
1. --myisam-recover-options=mode
设置为崩溃MyISAM表自动恢复的模式
2. --delay-key-write=ALL
对任何MyISAM表的写操做之间不要刷新键缓冲区。
注释:若是要这么作。当MyISAM表在使用中之时,不该该使用另外一个程序来访问它(好比从另外一个MySQL服务器或用myisamchk)。这么作会致使索引被破坏。对使用--delay-key-write的表,--external-locking不会生效
如下系统变量会影响 MyISAM 表的行为。有关其余信息, 请参见5.1.5 节 "服务器系统变量"。
1. bulk_insert_buffer_size
用在块插入优化中的树缓冲区的大小。注释:这是一个per thread的限制。
2. myisam_max_sort_file_size
在从新建立 MyISAM 索引 (在修复表、更改表或加载数据 INFILE 期间) 容许 MySQL 使用的临时文件的最大大小。若是文件大小大于此值, 则使用密钥缓存来建立索引, 这会比较慢。该值以字节为单位给出。
3. myisam_sort_buffer_size
设置恢复表时使用的缓冲区大小。
若是用--myisam-recover选项启动mysqld,自动恢复被激活。在这种状况下,当服务器打开一个MyISAM表之时,服务器会检查是否表被标注为崩溃,或者表的打开计数变量是否不为0且你正用--skip-external-locking运行服务器。若是这些条件的任何一个为真,下列状况发生:
1. 表被查错。
2. 若是服务器发现一个错误,它试着作快速表修复(排序且不从新建立数据文件)。
3. 若是修复由于数据文件中的一个错误而失败(例如,一个重复键错误),服务器会再次尝试修复,这一次重建数据文件。
4. 若是修复仍然失败,服务器用旧修复选项方法再重试一次修复(一行接一行地写,不排序)。这个方法应该能修复任何类型的错误,而且须要很低的磁盘空间。
若是恢复不可以从先前完成的语句里恢复全部行,并且你不能在--myisam-recover选项值指定FORCE,自动修复会终止,并在错误日志里写一条错误信息:
Error: Couldn't repair table: test.g00pages
若是你指定FORCE,取而代之地,相似这样的一个警告被给出:
Warning: Found 344 of 354 rows when repairing ./test/g00pages
注释:若是自动恢复值包括BACKUP,恢复进程建立文件并用tbl_name-datetime.BAK形式取名。你应该有一个cron脚本,它自动把这些文件从数据库目录移到备份媒质上。
键所需的空间
1. MyISAM表使用B型树索引。你能够粗略地计算索引文件的大小为(key_length+4)/0.67, 加上全部的键之和。当全部键以排序的顺序插入而且表没有任何压缩的键之时,以上估计是对最坏的状况的。
2. 字符串索引是被空间压缩的。若是第一个字符串索引部分是字符串,它也被加前缀压缩。若是字符串列有许多拖曳空间,或字符串 列是一个老是不用彻底长度的VARCHAR列,空间压缩使得索引文件比最坏状况时的数值要小。前缀压缩被用在以字符串开始的键上。若是有许多具备同一前缀的字符串,前缀压缩是有帮助的。
3. 在MyISAM表,你也能够在建立表的时候经过指定PACK_KEYS=1来前缀压缩数字。当数字被以高字节优先存储之时,若你有许多具备同一前缀的整数键,上述方法是有帮助的。
MyISAM表的存储格式
MyISAM 支持三种不一样的存储格式。根据所使用的列类型, 将自动选择其中的两个, 即固定和动态格式。第三个压缩格式只能使用 myisampack 实用程序建立 (请参见4.6.5 节 "myisampack 生成压缩的只读 MyISAM 表")。
当你CREATE或ALTER一个没有BLOB或TEXT列的表,你能够用ROW_FORMAT表选项强制表的格式为FIXED或DYNAMIC。这 会致使CHAR和VARCHAR列因FIXED格式变成CHAR,或因DYNAMIC格式变成VARCHAR。
有关 ROW_FORMAT 的信息, 请参见13.1.18 节 "建立表语法"。
您可使用 myisamchk --unpack 解压 (unpack) 压缩的 MyISAM 表,“myisamchk — MyISAM Table-Maintenance Utility”的详细信息见4.6.3章节
静态(固定长度)表特征
1. 静态格式是MyISAM表的默认存储格式。当表不包含变量长度列(VARCHAR, BLOB, 或TEXT)时,使用这个格式。每一行用固定字节数存储。
2. 在三 MyISAM 存储格式中, 静态格式是最简单、最安全的 (最不受损坏的)。因为能够轻松地在磁盘上找到数据文件中的行, 所以它也是最快的on-disk格式: 当按照索引中的行号查找一个行时,用行长度乘以行号。一样,当扫描一个表的时候,很容易用每一个磁盘读操做读必定数量的记录。
3. 若是您的计算机在 MySQL 服务器写入固定格式的 MyISAM 文件时崩溃, 安全是显然的。在这种状况下, myisamchk 能够很容易地肯定每行的开始和结束位置, 所以它一般能够回收除了部分写入以外的全部行(缓冲区中未写入的全部行)。MyISAM 表索引始终能够基于数据行进行重建。
注意:固定长度行格式仅适用于没有 BLOB 或TEXT列的表。使用显式 ROW_FORMAT 子句建立具备BLOB 或TEXT这些列的表不会引起错误或警告; 格式规范将被忽略。
静态格式表的通常特征:
1. CHAR 和 VARCHAR 列的空间填充到指定的列宽,尽管列类型未被更改。BINARY和 VARBINARY 列用0x00 字节填充到列宽。
2. NULL 列须要行中的额外空间来记录它们的值是否为 NULL。每一个 NULL 列须要一个额外的位, 四舍五入到最近的字节。
3. 很是快。
4. 容易缓存。
5. 在崩溃后易于重建, 由于数据行位于固定位置。
6. 除非删除大量的行并但愿将可用磁盘空间返回给操做系统, 不然无需进行重组。为此, 请使用 OPTIMIZE TABLE 或 myisamchk -r。
7. 一般比动态格式表须要更多的磁盘空间。
8. 使用如下表达式计算静态大小行的预期行长度 (以字节为单位):
row length = 1
+ (sum of column lengths)
+ (number of NULL columns + delete_flag + 7)/8
+ (number of variable-length columns)
对于具备静态行格式的表, delete_flag 为1。静态表在行记录中使用位, 用于指示是否已删除行的标志。delete_flag 是0用于动态表, 由于该标志存储在动态行标题中。
动态表特性
若是一个MyISAM表包含任何可变长度 列(VARCHAR, BLOB或TEXTDynamic),或者若是一个表被用ROW_FORMAT=DYNAMIC选项来建立,动态存储格式被使用。
动态格式比静态格式稍微复杂一些,由于每行有一个代表行有多长的头。当一个记录由于更新的结果被变得更长,该记录也能够在超过一个位置处结束。
可使用OPTIMIZE TABLE或myisamchk -r来对一个表整理碎片。若是在一个表中有频繁访问或改变的固定长度列,而且表中也有一些可变长度列,为避免碎片而把这些可变长度列移到其它表多是一个好主意。
动态格式表的通常特征:
1. 除了长度少于4的列外,全部的字符串列是动态的。
2. 每行前面都有一个位图, 指示哪些列包含空字符串 (对于字符串列) 或0 (对于数值列)。这不包括包含 NULL 值的列。若是字符串列在尾随空格后的长度为0, 或者数值列的值为0, 则在位图中标记, 而不保存到磁盘。非空字符串保存为一个长度字节加上字符串内容。
3. NULL 列须要行中的额外空间来记录它们的值是否为 NULL。每一个 NULL 列须要一个额外的位, 四舍五入到最近的字节。
4. 一般比固定长度表须要更少的磁盘空间
5. 每行只使用所需的空间。可是, 若是行变得更大, 则会将其拆分为所需的多个片段, 从而致使行碎片。例如, 若是使用扩展行长度的信息更新行, 则该行将变得有碎片。在这种状况下, 您可能须要时不时运行OPTIMIZE TABLE或myisamchk -r以提升性能。使用 myisamchk -ei 获取表统计信息。
6. 比静态格式表在崩溃后重建更困难, 由于行可能会被分割成许多片断和连接 (碎片), 可能会在重建时丢失。
7. 使用如下表达式计算动态大小行的预期行长度:
row length = 3
+ (number of columns + 7) / 8
+ (number of char columns)
+ (packed size of numeric columns)
+ (length of strings)
+ (number of NULL columns + 7) / 8
8. 对每一个连接须要额外的6字节。在一个更新致使一个记录的扩大之时,一个动态记录被连接了。每一个新连接至少是20字节,因此下一个扩大可能在一样的连接里进行。若是不是,则另外一个连接将被创建。你可使用myisamchk -ed来找出连接的数目。全部的连接能够用 OPTIMIZE TABLE 或 myisamchk -r来移除。
压缩表特性
已压缩存储格式是由myisampack工具建立的只读格式。
已压缩表能够用myisamchk来解压缩。
压缩表有下列特征:
1. 已压缩表占据很是小的磁盘空间。这最小化了磁盘用量,当使用缓慢的磁盘(如CD-ROM)之时,这是颇有用的。
2. 每一个记录是被单独压缩的,因此只有很是小的访问开支。依据表中最大的记录,一个记录的头在每一个表中占据1到3个字节。每一个 列被不一样地压缩。一般每一个列有一个不一样的Huffman树。一些压缩类型以下:
2.1 后缀空间压缩。
2.2 前缀空间压缩。
2.3 零值的数用一个位来存储。
2.4 若是在一个整型列中的值有一个小的范围,列被用最小可能的类型来存储。好比,一个BIGINT列(8字节),若是全部它的值在-128到127范围内,它能够被存储为TINYINT列(1字节)
2.5 若是一个列仅有一小组可能的值,列的类型被转化成ENUM。
2.6 一个列可使用先前压缩类型的任意合并。
3. 能够处理固定长度或动态长度记录。
注意
虽然压缩表是只读的, 所以不能在表中更新或添加行, 但 DDL (数据定义语言) 操做仍然有效。例如, 您仍然可使用 drop 除去表, 并截断表以清空表。
MyISAM 表问题
MySQL用来存储数据的文件格式已经被普遍测试过,但老是有致使数据表变得损坏的环境。
损坏的MyISAM表
即便MyISAM表格式很是可靠(SQL语句对表作的全部改变在语句返回以前被写下),若是下列任何事件发生,你依然能够得到损坏的表:
1. mysqld 进程在写入过程当中被杀死。
2. 发生意外的计算机关机 (例如, 计算机被关闭)。
3. 硬件故障。
4. 使用外部程序 (如 myisamchk) 修改正在被服务器修改的表。
5. MySQL 或 MyISAM 代码中的bug。
表损坏的典型症状为:
1. 从表中查询数据时会出现如下错误:
Incorrect key file for table: '...'. Try to repair it
2. 查询在表中找不到行或返回不完整的结果。
可使用 CHECK TABLE语句检查 MyISAM 表的健康情况, 并用REPAIR TABLE修复损坏的 MyISAM 表。当 mysqld 未运行时, 还可使用 myisamchk 命令检查或修复表。
参阅 13.7.2.2 章节 “CHECK TABLE Syntax”, 13.7.2.5 章节 “REPAIR TABLE Syntax”, 4.6.3 章节, “myisamchk — MyISAM Table-Maintenance Utility”.
若是表频繁损坏, 则应尝试肯定发生此事件的缘由。最重要的是要知道该表是否因服务器崩溃而损坏。经过在错误日志中查找最近 restarted mysqld 消息, 进行验证。若是有这样的消息, 表损坏极可能是服务器崩溃致使的。不然, 损坏可能发生在正常操做期间。这是个 bug。您应该尝试建立一个可重现的测试用例来演示问题。
参阅 B.5.3.3 章节 “What to Do If MySQL Keeps Crashing”, 28.5 章节 “Debugging and Porting MySQL”.
未正确关闭表的问题
每一个 MyISAM 索引文件 (.MYI文件) 在头部有一个计数器, 可用于检查表是否已正确关闭。若是从CHECK TABLE或 myisamchk 获得如下警告, 则表示此计数器已经不一样步了:
clients are using or haven't closed the table properly
此警告不必定意味着该表已损坏, 但至少应检查表。
该计数器的工做原理以下:
1. 第一次在 MySQL 中更新表时, 索引文件头部中的计数器将递增。
2. 在将来的更新中, 计数器不会更改。
3. 当表的最后实例被关闭(由于一个操做FLUSH TABLE或由于在表缓冲区中没有空间)之时,若表已经在任何点被更新,则计数器减一。
4. 当修复表, 或检查表时它被发现是好的, 计数器被重置为零。
5. 为了不与其它可能检查表的进程进行交互的问题,若计数器为零,在关闭时计数器不减一。
换言之, 只有在下列状况下, 计数器才会变得不正确:
1. 复制 MyISAM 表, 不先 LOCK TABLES 和 FLUSH TABLES
2. MySQL在一次更新和最后关闭之间崩溃(注意,表可能依然无缺,由于MySQL老是在每一个语句之间为每件事发出写操做)
3. 一个表被mysqld使用的同时,又被myisamchk --recover或myisamchk --update-state修改。
4. 多个 mysqld 服务器正在使用该表, 一台服务器在其被另外一台服务器使用时在表上执行了修复表或检查表。在这个架构中, 使用CHECK TABLE是安全的, 尽管可能从其余服务器获得警告。可是, 应避免REPAIR TABLE, 由于当一个服务器用一个新的数据文件替代旧的之时,其余服务器不知道这一点。
总的来讲,在多服务器之间共用一个数据目录是一个坏主意。
参阅 5.6 章节 “Running Multiple MySQL Instances on One Machine” 得到更多研讨。