1.5.1 InnoDB存储引擎

InnoDB是MySQL的默认事务引擎,也是最重要、使用最广泛的存储引擎。它被设计用来处理大量的短期(short-lived)事务,短期时间大部分情况都是正常提交的,很少会被回滚。InnoDB的性能和自动奔溃恢复特性,使得它在非事务型存储的需求中也很流。除非有特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。

InnoDB的数据存储在表空间(tablespace)中,表空间是由InnoDB管理的一个黑盒子,由一系列的数据文件组成。在MySQL4.1以后的版本中。InnoDB可以将每个表的的数据和索引存放在单独的文件中。InnoDB也可以使用裸设备作为表空间的存储介质,但现代的文件系统使得裸设备不再是必须要的选择。
InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。其默认级别是可重复读,并且通过间隙锁(next-key locking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插入。
InnoDB是基于聚簇索引建立的。InnoDB的索引结构和MySQL的其他存储引擎有很大的不同,聚簇索引对主键查询有很高的性能。不过它的二级索引(非主键索引)中必须包含主键列,所以如果主键列很大的话,其他的所有索引都会很大,因此,若表上的索引较多的话,主键应当尽可能的小。InnoDB的存储格式是平台独立的,也就是说可以将数据和索引文件从Intel平台复制到PowerPC或者Sun APAPC平台。
InnoDB内部做了很多优化,包括从磁盘读取数据时采用的可预测性预读,能够自动在内存中创建hash索引以加速读操作的自适应哈希索引,以及能够加速插入操作的插入缓存区等。
作为事务性的存储引擎,InnoDB通过一些机制和工具支持真正的热备份,Oracle提供的 MySQL Enterprise Backup 、Percona提供的开源XtraBackup都可以做到这一点。

1.5.6 转换表的引擎

ALTER TABLE

将表从一个引擎修改为另一个引擎最简单的办法是使用ALTER TABLE语句。

  1. ALTER TABLE mytable ENGINE=InnoDB;

上述语句可以实用任何存储引擎。但有一个问题:需要执行很长时间。MySQL会按行将数据从原表复制一张到新的表中,在复制期间可能会消耗系统所有的I/O能力,同时原表上会加上读锁。所以,在繁忙的表上执行此操作要特别小心。一个替代方案是采用导入导出的方法,手工进行复制。

如果转换表的存储引擎,将会失去和原来引擎相关的所有特性。例如一张InnoDB表转换成MyISAM,然后再转换会InnoDB,原InnoDB表上所有的外键将丢失。

导入与导出

为了更好地控制转换的过程,可以使用mysqldump工具将数据导出到文件,然后修改文件中的CREATE TABLE语句的存储引擎选项,注意同时修改表名,因为一个数据库中不能存在相同的表名。即使他们使用的是不同的存储引擎。同时要注意mysqldump默认会自动在CREATE table语句前加上 DROP TABLE语句,不注意这点可能会导致数据丢失。

创建与查询(CREATE 和select)

第三种转换的技术综合了第一种方法的高效和第二种方法的安全。不需要导出整个表的数据,而是先创建一个新的存储引擎的表,然后 INSERT … SELECT语法

  1. CREATE TABLE innodb_table LIKE myisam_table;
  2. ALTER TABLE innodb_table ENGINE=InnoDB;
  3. INSERT INTO innodb_table SELECT * FROM myisam_table ;

数量量不大的话,这样做工作得很好。如果数量很大,则可以考虑做分批处理。针对每一段数据执行事务提交操作,以避免大事务产生过多的undo。加入有主键字段id,可以如下

  1. START TRANSACTION;
  2. INSERT INTO innodb_table SELECT * FROM myisam_table
  3. WHERE id BETWEEN x AND y;
  4. COMMIT;

Percona Toolkit提供了一个pt-online-schema-change的工具,可以比较简单、方便地执行上述过程,避免手工操作可能导致的是失误和烦琐。