【MySQL学生手册】常用存储引擎 – MyISAM

本文地址:https://www.askmac.cn/archives/mysql-storage-engines-myisam.html

 

8.2 常用存储引擎

MySQL可以使用多种存储引擎来进行工作,因此针对特定需求,用户可以有许多选择。以下为MySQL的一些常用存储引擎(包括了简单的特性比较):

 

MyISAM InnoDB MEMORY
Ÿ   速度快

Ÿ   数据存储在.MYD表文件中

Ÿ   表级锁

Ÿ   支持事务(COMMIT/ROLLBACK)

Ÿ   支持外键

Ÿ   行级锁

Ÿ   数据仅在内存中(如果服务端关闭则数据丢失)

 

8.2.1 MyISAM存储引擎

 

MyISAM存储作为曾经MySQL的默认存储引擎。它所管理的表具有以下特性:

  • 其每个表使用三个文件:
    • 一个格式文件 — 存储表结构定义(frm)
    • 一个数据文件 — 存储表行内容(MYD)
    • 一个索引文件 — 存储表上索引(MYI)
  • 和其他存储引擎一样提供AUTO_INCREMENT列处理
  • 可被转换为可快速访问,压缩的,只读表以节约空间
  • 使用表级锁来管理对MyISAM表访问的查询争用
  • 支持全文索引来查询空间数据类型数据
  • 支持GIS地理空间扩展
  • 表存储格式是便携的,意思是表文件可以直接拷贝至其它主机并被其主机中的服务端所用。
  • 可定义表必须能够存放的最少行数。
  • 当将数据倒入一张空表时,你可以禁用对非唯一索引的更新并在倒入完成后再启用这些索引。
和老式ISAM表相同,MyISAM表使用索引顺序访问方式在进行索引建立。不过MyISAM比ISAM提供更好的性能,因此在MySQL 5.0之后ISAM不在可用,而倾向于使用MyISAM。

 

MyISAM行存储格式:

MyISAM可以以三种格式来存储表行数据:fixed-row, dynamic-rowcompressed。这三种格式具有不同特点:

fixed-row(固定行)格式:

  • 所有行具有相同大小。
  • 行所在表中的位置可以通过行大小的倍数进行计算,这方便了查找。
  • 固定大小的行会占用更多空间(除非数据都是固定长度的,那么实际上会占用更少空间)

dynamic-row(动态行)格式:

  • 行占用空间大小是变化的。
  • 行位置查找相对效率会低一些。
  • 因为动态行表中的行不会按固定行大小来填充,所以通常占用更少空间。

compressed(压缩)格式:

  • 表被压紧以节约空间。
  • 存储被优化以快速获取数据。
  • 表成为只读表。

 

MyISAM锁:

MyISAM锁发生在表级。在一个读写混合的环境中,对于并行执行来说并非所期待的页锁或者行锁。死锁会随着任何事务而发生。

 

当在MyISAM表上处理查询时,同时运行的客户端通过隐式地获取对表所需锁,使得服务端得以管理资源的争用。你也可以显式地使用LOCK TABLES和UNLOCK TABLES语句来进行锁表操作。

 

MyISAM表支持并行插入。如果一张MyISAM表中部不存在空洞的话(由于删除或更新记录造成的),那么insert的记录总是会在表尾被插入,而且插入操作可以在其它客户端读取此表时进行。如果客户端获取的是READ LOCAL锁,而不是通常的READ锁的话,那么即便是显式获取的锁,在对应的表上仍然可以进行并行插入操作。

 

 

如果表中确实存在空洞,那么默认情况下就不能进行并行插入。不过,你可以使用OPTIMIZE TABLE来去除表中的碎片空洞(注意,如果你之前删除的记录处于表最后,且删除并不会产生空洞的话,这就不会妨碍到并行插入)。或者你可以设置concurrent_insert系统变量值为2或ALWAYS(作用和mysqld –concurrent-insert命令项相同),这样就强制允许并行插入了,且即便存在行删除,新插入的行也会被加入在表的最后。

 

对于那些使用MyISAM表的应用,你可以修改语句优先级来获取或修改数据。这对于当正常安排的优先级不能满足应用需要时非常有用。

 

默认情况下,服务端对语句执行的优先级安排如下:

  • 写请求(如UPDATE和DELETE语句)优先级高于读请求(如SELECT语句)。
  • 服务端会按收到写请求的顺序依次执行写请求。

 

然而,如果一张表正在被读取而此时来了一个写请求,其写请求在所有当前读完成前是无法被处理的。任何在写请求到达之后的读请求都必须等待写请求完成,即便当前的写请求也在等待当前处理的读请求完成,也如此。也就是说,一个新的读请求默认情况下是不会跳到一个当前正等待的写请求之前的。

 

当使用MyISAM表处理数据时,某些语句的修饰符可用于改变请求的优先顺序:

 

  • LOW_PRIORITY修饰符可被用于语句中来对表进行更新(INSERT,DELETE或UPDATE)。一个低优先级的写请求不仅需要等所有当前在处理的读请求完成,还需要等待在其保持等待时已经在等待和收到的读请求。这意味着,它需要等到没有任何等待的读请求,都完成后才能开始处理。如果读请求源源不断的话,这很有可以造成低优先级写请求永远不被处理,一直等待。
  • HIGH_PRIORITY可被用于SELECT语句来将其排于其它UPDATE和那些不使用HIGH_PRIORITY作为其修饰符的SELECT语句之前。
  • DELAYED可以和INSERT(和REPLACE)一起使用。服务端将插入行缓存在内存中,当表不再被使用时,再从内存中清出并插入表中。由于这种推迟插入是批量的而非独立的,因此非常有效率。当插入行时,服务端会定时查看是否表有收到其它请求。如果有,那么服务端会暂停这些被推迟行的插入,直到表重新自由可用时再进行。使用DELAYED允许客户端在发出INSERT语句后可立刻进行处理,而不需要等到它完成。(注意:由于性能等多种原因,DELAYED在MySQL 5.6.6开始将被淘汰,在5.7版本开始已经被无视为普通INSERT语句,将来此修饰符会被移除)

 

我们假设有这样一个应用,其包含有一个日志进程来使用INSERT语句在一个日志表中记录信息,有一个汇总进程定时的发出SELECT查询来从日志表中生成报告。正常情况下,服务端会对表的更新操作比数据查询更高的优先级,因此在日志活动繁忙时,报告的生成会被延误。如果应用希望汇总处理能具有高优先级并尽可能快的完成,那就可以使用修饰符来改变通常的查询优先级。有两种方法可以实现:

  • 为了提升汇总查询的优先级,使用SELECT HIGH_PRIORITY语句而非仅使用SELECT。这会将SELECT查询优先于那些还未开始执行的INSERT语句。
  • 为了降低INSERT语句的优先级,使用LOW_PRIORITY或DELAYED修饰符来和INSERT一起使用。

 

如果你使用DELAYED,请注意:

  • 被推迟的行会在服务端非常繁忙时趋向于比普通的插入花更长时间再处理。
  • 如果被推迟的行还在内存中,这时发生的数据库服务端崩溃,那么这些行会丢失。

 

从以上我们可以了解,DELAYED更适用于那些对丢失行数据并非大问题的应用,而非对那些每行数据都不可丢失的应用。例如,DELAYED作为对某些日志活动的记录应用较为适合,因为即便丢失了少量行记录也不是很重要。

 

MyISAM的优点和缺点:

优点 缺点
Ÿ   没有实际存储限制;表大小限制仅受限于文件大小限制

Ÿ   低存储成本(有效的存储处理)

Ÿ   支持B-Tree, FullText和GIS索引

Ÿ   快速的查询性能

Ÿ   快速的查询性能

Ÿ   在表中维护存储有精确的行计数(select count(*)非常快)

Ÿ   支持前缀长度索引(prefix-length index)

Ÿ   不支持事务

Ÿ   表级锁

Ÿ   不支持外键

 

 

 

Comment

*

沪ICP备14014813号-2

沪公网安备 31010802001379号