MySQL有多种存储引擎:
MyISAM、InnoDB、MERGE、
MEMORY(HEAP)、
BDB(BerkeleyDB)、EXAMPLE、FEDERATED、
ARCHIVE、CSV、BLACKHOLE、
NDB。
MySQL支持数个存储引擎作为对不同表的类型的处理器。MySQL存储引擎包括处理事务安全表的引擎和处理非事务安全表的引擎:
下述存储引擎支持事务:
·InnoDB:通过MVCC支持事务,允许COMMIT、ROLLBACK和保存点。
·NDB:通过MVCC支持事务,允许COMMIT和ROLLBACK。
·BDB:支持事务,允许COMMIT和ROLLBACK。
(事务就是把多件事情当做一件事情来处理。也就是大家同在一条船上,要活一起活,要挂一起挂)
存储引擎比较
常用的存储引擎
·MyISAM:默认的MySQL插件式存储引擎,它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。注意,通过更改STORAGE_ENGINE配置变量,能够方便地更改MySQL服务器的默认存储引擎。
·InnoDB:用于事务处理应用程序,具有众多特性,包括ACID事务支持。
·BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其他事务特性。
·Memory:将所有数据保存在RAM中,在需要快速查找引用和其他类似数据的环境下,可提供极快的访问。
·Merge:允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起,并作为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。
·Archive:为大量很少引用的历史、归档、或安全审计信息的存储和检索提供了完美的解决方案。
·Federated:能够将多个分离的MySQL服务器链接起来,从多个物理服务器创建一个逻辑数据库。十分适合于分布式环境或数据集市环境。
·Cluster/NDB:MySQL的簇式数据库引擎,尤其适合于具有高性能查找要求的应用程序,这类查找需求还要求具有最高的正常工作时间和可用性。
·Other:其他存储引擎包括CSV(引用由逗号隔开的用作数据库表的文件),Blackhole(用于临时禁止对数据库的应用程序输入),以及Example引擎(可为快速创建定制的插件式存储引擎提供帮助)。
将存储引擎指定给表
可以在创建新表时指定存储引擎,或通过使用ALTER TABLE语句指定存储引擎。
要想在创建表时指定存储引擎,可使用ENGINE参数:
CREATE TABLE engineTest(id INT) ENGINE = MyISAM;
要想更改已有表的存储引擎,可使用ALTER TABLE语句:
ALTER TABLE engineTest ENGINE = ARCHIVE;
插入存储引擎
能够使用存储引擎之前,必须使用INSTALL PLUGIN语句将存储引擎plugin(插件)装载到mysql。例如,要想加载example引擎,首先应加载ha_example.so模块:
INSTALL PLUGIN ha_example SONAME ‘ha_example.so‘;
拔出存储引擎
要想拔出存储引擎,可使用UNINSTALL PLUGIN语句:
UNINSTALL PLUGIN ha_example;
如果拔出了正被已有表使用的存储引擎,这些表将成为不可访问的。拔出存储引擎之前,请确保没有任何表使用该存储引擎。
查看当前默认引擎
查看当前的默认存储引擎,可以使用
show variables like ‘table_type‘;
结果如下:
mysql> show variables like ‘table_type‘;
+---------------+--------+
| Variable_name | Value |
+---------------+--------+
| table_type | InnoDB |
+---------------+--------+
1 row in set
查询数据库支持的存储引擎
mysql> show engines;
mysql> show engines;
+------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+------------+---------+----------------------------------------------------------------+--------------+------+------------+
| MyISAM | YES | Default engine as of MySQL 3.23 with great performance | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
| InnoDB |
DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
|
MEMORY | YES | Hash based, stored in
memory, useful for temporary tables | NO | NO | NO |
+------------+---------+----------------------------------------------------------------+--------------+------+------------+
8 rows in set
mysql>
不应该在mysql数据库(比如,user或者host)里把MySQL系统表转换为InnoDB类型。
系统表总是MyISAM型。
如果你想要所有(非系统)表都被创建成InnoDB表,你可以简单地把default-table-type=innodb行添加到my.cnf或my.ini文件的[mysqld]节里。
如果要修改默认引擎可以在参数文件中设置
default-table-type
default-storage-engine
确定一张指定表的存储引擎
如果想要确定一张指定表的存储引擎是什么,可以使用
SHOW TABLE STATUS命令来决定。例如,想要确定mysql数据库中的user表的存储引擎,可以执行如下命令:
show table status like ‘user‘;
Name
表的名称
Engine
表的存储引擎。在早些的MySQL版本中,这一列被称为Type而不是Engine。
Row_format
行的格式。对于一个MyISAM表来说,这个项的取值可能为Dynamic,Fixed或者Compressed。动态行(Dynamic)表示它的一行数据的长度是可变的,因为它包含了一个变长的字段类型,比如VARCHAR或者BLOB。固定行(Fixed)有固定的大小,均是由不可变长度的类型组成的,比如CHAR和INTEGER。压缩行(Compressed)只存在于压缩的表中,详细的信息可以查看“压缩的MyISAM表”。
Rows
表中当前的行数。对于非事务型表来说,这个数字总是很准确的,但是对于事务型的表来说,这只是一个估计。
Avg_row_length
平均每一行有多少byte的数据
Data_length
整张表一共包含了多少数据(以byte为单位)
Max_data_length
这个表可以使用的最大数据空间。
Index_length
索引数据所使用的磁盘空间大小
Data_free
对于一个MyISAM表来说,这是指分配给表但是却没有使用的磁盘空间。这个空间包含以前删除的行,并且这些空间可以通过将来的INSERT语句来回收。
Auto_increment
下一个AUTO_INCREMENT值
Create_time
当前表被第一次创建的时间
Update_time
当前表最后一次的修改时间
Check_time
当前表最后一次用CHECK TABLE语句或者myisamchk命令进行检查的时间
Collation
当前表的默认的字符集以及针对字符列的排序。
Checksum
如果这个功能被雇用的话,代表整张表内容的一个实时检验和
Create_options
任何在创建表时指定的其他选项。
Comment
这一列包含了一个的变长的额外信息。对于一个MyISAM表来说,它包含了注释,这个值是在表创建时指定的。如果是InnoDB存储引擎,那么表空间的可使用大小会在这里显示。如果是一个视图,那么本项显示为“VIEW”。
MyISAM
MyISAM是默认存储引擎。它基于更老的ISAM代码,但有很多有用的扩展。(注意MySQL 5.1不支持ISAM)。
每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。 MyISAM文件的格式是平台无关的,这意味着你可以将数据和索引文件从一个intel服务器上拷贝到一台PowerPC或者Sun SPARC上,而不会出任何问题。
(C:\Documents and Settings\All Users\Application Data\
MySQL\
MySQL Server 5.1\data)
要明确表示你想要用一个MyISAM表格,请用ENGINE表选项指出来:
CREATE TABLE t (i INT) ENGINE = MYISAM;
注释:老版本的MySQL使用TYPE而不是ENGINE(例如,TYPE = MYISAM)。MySQL 5.1为向下兼容而支持这个语法,但TYPE现在被轻视,而ENGINE是首先的用法。
一般地,ENGINE选项是不必要的;除非默认已经被改变了,MyISAM是默认存储引擎。
MyISAM表可以包含动态或者静态的行。MySQL根据表定义来决定使用哪一种格式。一个MyISAM表所能包含的数据一般由你的数据库服务器的磁盘空间和操作系统所允许的最大文件大小来决定。
MySQL5.0中创建的具有动态长度的MyISAM表默认可以处理256TB的数据,它使用一个6字节的指针来表示数据记录。早期的 MySQL版本默认使用4字节的指针,因此它最大可以存储4GB的数据。所有的MySQL版本都可以处理最大8字节的指针。如果想要改变MyISAM表上的指针大小,可以通过指定MAX_ROWS以及AVG_ROW_LENGTH选项来共同决定
MySQL中使用的最早的存储引擎,MyISAM具有众多优秀特性:
锁和并发
MyISAM锁定整张表而不是行。读者在需要读时可以获取一个共享的读锁。写者在需要时可以得到一个互斥的写锁。但是当一个查询操作正在进行时,你还是可以插入一条记录到表中。这是一个非常重要而且有用的特性。
自动修复
MySQL支持MyISAM表的自动检查和修复。
手动修复
你可利用CHECK TABLE或者REPAIR TABLE语句来检查一个表的错误并且修复它们。你同样可以在服务器离线的情况下利用myisamchk命令行工具来检查和修复表。
检索特性
你可以创建在MyISAM表中为BLOB或者TEXT类型的列的前500个字符创建索引。MyISAM支持全文索引,这种索引会分词,以用来处理一些复杂的查询。如果想要了解更多的关于索引的信息,可以查看第3章。
延迟的索引更新
MyISAM表如果在创建选项里指定为DELAY_KEY_WRITE的话,它不会立即将改变的索引数据写到硬盘,而是将这个改变缓存到内存中。当表被关闭或者缓冲区需要修整时,它会将索引一次性写到硬盘。这个特性可以在修改很频繁的表上极大的提高性能。但是当一个服务器或者操作系统崩溃时,这些索引肯定会被损坏,当然也需要修复。你可通过写一个脚本来在每次重启服务器前先用myisamchk来检查一下,或者你也可以使用自动修复选项。(即使你不使用DELAY_KEY_WRITE,这些安全性保障也是一个很好的习惯。)你既可以对整个数据库设置延迟的索引更新,也可以只针对某些表来进行设置。
InnoDB存储引擎
InnoDB是为事务处理而设计的,特别是为处理多而生存周期比较短的事务而设计,一般来说这些事务基本上都会正常结束,只有少数才会回滚。
它是目前事务型存储引擎中最为著名的。它的性能和自动故障恢复使得它同时也作为一个优秀的非事务存储引擎被广泛使用。
InnoDB将数据存储在一个或者多个被共同称为表空间的文件中。一个表空间基本上作为一个黑盒子而由InnoDB自己来维护。在 MySQL4.1以及之后的版本中,InnoDB都可以将每个表的数据以及索引存储到不同的文件中。InnoDB还可以利用磁盘分区功能来创建它的表空间。
InnoDB利用MVCC来实现高并发性,并且它也实现了SQL的4种标准隔离级别。它的默认隔离级别是“可重复读REPEATABLE READ”,同时它还利用一种“next-key锁定”策略来防止这个级别的幻读;
另外InnoDB并不是只锁定你在一个语句中使用到的记录,它同时会锁定索引结构的缺口,以防止幻写。
InnoDB表是基于一种被称为“簇索引”之上的, InnoDB的索引结构与其他的MySQL存储引擎很不相同。事实上,它能够提供基于主键的非常快速的查询。但是由于二级索引(非主键的索引)都会包含主键列,因此如果你的主键如果很大的话,将会导致你的索引整个会变得很大。如果你的表上有许多的索引的话,你应该尽可能的使用一个小的主键。InnoDB不会压缩它的索引。
InnoDB还不能依赖于排序来构造索引,这一点MyISAM是支持的。因此InnoDB加载数据和创建索引相对于MyISAM来说会慢一些。任何会改变InnoDB表结构的操作都会引起整个表的重建,包括所有的索引。
(注释:绿色字体部分为访问速度差距原因)
InnoDB的下一个著名的特性是外键约束,这一点MySQL服务器本身并不支持。InnoDB提供了基于主键的极快速的查询。
InnoDB有许多的内部优化。这包括预见性地从硬盘上将数据事先读到内存,自适应的在内存中进行哈希索引构建以期得到快速查询,以及用来提高插入速度的插入记录缓冲。
BDB
BDB表可能有一个更大的崩溃幸存机会,并且也具有对事务COMMIT和ROLLBACK操作的能力。
每个BDB表用两个文件被存在磁盘上。文件的名字用表的名字做开头,并且有一个扩展名来指明文件类型。一个.frm文件存储表定义,一个.db文件包含表数据和索引。
BDB存储引擎提供事务性表,你使用这些表的方法取决于autocommit模式:
·如果你正运行着,同时随着autocommit的被允许(这是默认的),对BDB表的改变被立即提交并且不能被回滚。
·如果你正运行着,同时随着autocommit的被禁止,改变不变成永久的直到你执行一个COMMIT语句。作为提交的替代,你可以执行ROLLBACK来忘记改变。
你可以用BEGIN WORK语句开始一个事务来挂起autocommit,或者用SET AUTOCOMMIT=0来明确禁止autocommit。
BDB表可以有多达每表31个索引,每个索引16列,并且1024字节的最大键尺寸。
MySQL在每个BDB表中需要一个PRIMARY KEY以便每一行可以被唯一地识别。如果你不明确创建一个,MySQL为你创建并维持一个隐藏的PRIMARY KEY。隐藏的键有一个5字节的长度,并且为每个插入的企图而被增加。这个键不出现在SHOW CREATE TABLE或DESCRIBE的输出之中。
PRIMARY KEY比任何其它索引都要快,因为PRIMARY KEY被与行的数据一起存储。其它索引被存储为键数据+PRIMARY KEY,所以保持PRIMARY KEY尽可能地短以节约磁盘空间并获得更好速度是重要的。
这个行为类似于InnoDB的,在其中较短的primary keys不仅在主索引也在第二索引节约空间。
·如果在BDB表中,你访问的所有列是同一索引的一部分或主键的一部分,MySQL可以执行查询而不访问确实的行。在一个MyISAM表中,只有列是同一索引的一部分之时,才可以这么做。
·连续扫描比对MyISAM表的扫描更慢,因为在BDB表中的数据被存储在B树而不是在分离的数据文件中。
·键值象MyISAM表中的键值一样不是前缀或后缀压缩的。换句话说,在BDB表中键信息只比在MyISAM表中稍微多占据一点空间。
·在BDB表中经常有洞允许你在索引树的中间插入新行。这个使得BDB表比MyISAM表稍微大一些
·SELECT COUNT(*) FROM
tbl_name对BDB表很慢,因为在该表中没有行计数被维持。
·BDB表上的内部锁定在页面级别上做
·如果你在BDB表内遇到磁盘满,你得到一个错误(可能是错误28),并且事务应该回滚。这与MyISAM表相反,对于MyISAM 表,
mysqld在继续之前等待足够的自由磁盘空间。
对BDB表的限制
下列表说明使用BDB表之时你必须要遵从的限制:
·每个BDB表在.db文件里存储文件被创建之时到该文件的路径。这个被做来允许在支持symlinks的多用户环境里检测锁定。因此,从一个数据库目录往另一个目录移动BDB表是不能的。
·当制作BDB表的备份之时,你必须要么使用
mysqldump要么做一个包含对每个BDB表的文件(.frm和.db文件)及BDB日志文件的备份。BDB存储引擎在它的日志文件存储未完成的事务以及要求它们在
mysqld启动的时候被呈出来。BDB日志在数据目录里,具有log.XXXXXXXXXX(10位数字)形式名字的文件。
·如果允许NULL值的列有唯一的索引,只有单个NULL值是被允许的。这不同于其它存储引擎。
MERGE MyISAM
MERGE(MERGE MyISAM)引擎有很多特殊的地方:
MERGE引擎类型允许你把许多结构相同的表合并为一个表。然后,你可以执行查询,从多个表返回的结果就像从一个表返回的结果一样。每一个合并的表必须有同样的表定义。
MERGE存储引擎在下面这种使用场合会最为有用,如果需要把日志纪录不停的录入MySQL数据库,并且每天、每周或者每个月都创建一个单一的表,而且要制作来自多个表的合计查询,MERGE表这时会非常有效。然而,这项功能有局限性。你只能合并MyISAM表而且必须严格遵守相同的表定义的限制。虽然这看起来好像是一个大问题,但是,如果你使用另外一种表类型(例如InnoDB),这种合并可能就不需要了。
其创建方法如下:
他将多个表在逻辑上当作一个表来查询。他建立后有两个文件,
.frm 表结构定义
.mrg union表的名字清单
两个基本表:
CREATE TABLE TEST_MERGE_1(
ID INT(5) NOT NULL,
VALUE VARCHAR(100) NOT NULL,
PRIMARY KEY(ID)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
CREATE TABLE TEST_MERGE_2(
ID INT(5) NOT NULL,
VALUE VARCHAR(100) NOT NULL,
PRIMARY KEY(ID)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
MERGE表的建立:
CREATE TABLE TEST_MERGE(
ID INT(5) NOT NULL,
VALUE VARCHAR(100) NOT NULL,
PRIMARY KEY(ID)
) ENGINE=MRG_MyISAM DEFAULT CHARSET=utf8 INSERT_METHOD=LAST UNION=(TEST_MERGE_1,TEST_MERGE_2) ;
1. 此表类似于SQL中的union机制。
2. 此表结构必须与基本表完全一致,包括列名、顺序。UNION表必须同属一个DATABASE。
3. 基本表类型必须是MyISAM。
4. 可以通过修改.mrg文件来修改MERGE表,每个基本表的名字占一行。注意:修改后要通过FLUSH TABLES刷新表缓存。
5. 对基本表的更改可以直接反映在此表上。
6. INSERT_METHOD的取值可以是: 0 不允许插入 FIRST 插入到UNION中的第一个表 LAST 插入到UNION中的最后一个表。(4.0之后可用)
7. 定义在它上面的约束没有任何作用,约束是由基本表控制的,例如两个基本表中存在着同样的一个Key值,那么在MERGE表中会有两个一样的Key值。
8. 连接的几张表都必须是myisam engine的。
因为MySQL利用底层文件系统来保存数据库名和表定义,因此是否大小写敏感取决于使用的平台。在一个基于Windows的MySQL实例上,表和数据库名是大小写不敏感的;而在类Unix系统上,它们是大小写敏感的。每一种存储引擎对于数据和索引的存储是不一样的,但是关于表的定义却是由服务器层来完成的。
Memory存储
内存表(以前被称为HEAP表)当你需要极快速的获取一些不需要修改或不需要在重启后持久化的数据时会非常有用。内存表一般会比MyISAM表快上一个数量级。所有的数据都被存储在内存中,因此查询不需要磁盘IO等待。内存表的表结构在会服务器重启过程中进行持久化,但是数据不会。
下面是一些内存表比较好的应用:
作为查询表或者映射表,如邮编和省份的映射表
作为周期性更新的数据缓存表
作为分析数据的中间结构表
内存表支持HASH索引,HASH索引在查询中非常快速。关于“哈希索引”的具体内容可以查看后面章节。
创建,使用并删除一个
MEMORY表:
mysql>
CREATE TABLE test ENGINE=MEMORY ->
SELECT ip,SUM(downloads) AS down ->
FROM log_table GROUP BY ip;mysql>
SELECT COUNT(ip),AVG(down) FROM test;mysql>
DROP TABLE test;
尽管内存数据库很快,但是它们仍然不用作为一个基于硬盘表的替换产品。因为它只支持表级别的锁定,这使得它的写并发效率很快,另外它不支持 TEXT和BLOB类型。另外,内存数据库只支持固定大小的行,因此它会将VARCHAR作为CHAR来进行存储,这将会浪费许多内存。
MySQL将内存引擎作为处理查询时的中间结果的内部临时数据库来使用。如果中间结果太大或者有TEXT和BLOB列的话,MySQL会把内存表转换为MyISAM表。我们将在后面章节中详细讨论这个问题。
人们经常把内存表和临时表相混淆。事实上临时表是用CREATE TEMPORARY TABLE命令来他创建的。一个临时表可以使用任何存储引擎;它与使用内存引擎的表不是一回事。临时表仅对于单个的连接是可见的,当连接关闭时这个临时表就会被销毁。
Archive存储引擎
Archive引擎只支持INSERT和SELECT语句,并且它不支持索引。它比MyISAM使用更少的磁盘IO,因此它会在写操作之前将数据缓存并利用zlib来压缩。而SELECT查询操作则需要一个全表扫描。因此Archive表是日志和数据采集的理想选择,在这些应用中,一般分析是需要扫描整张表或者需要在一个备份主机上进行快速的INSERT操作。备份从机上可以为相同的表选用一个不同的存储引擎,这意味着从机上的表可以有索引,以达到快速分析的目的。
Archive引擎支持行级别的锁以及一个特殊的缓冲系统以期达到高并发的写操作。它在查询时会将整个表扫描一次。它同时也会将批量写操作屏蔽直到全部的写操作完成。这些特性模拟了事务和MVCC行为的一些方面,但是Archive引擎并不是一个事务型引擎。它只是一个优化了插入操作以及压缩了数据的引擎。
选择正确的存储引擎
当设计基于MySQL的应用时,你应该首先决定利用哪种存储引擎来存储你的数据。如果你不在设计阶段考虑这个问题,你极有可能在后面的开发中面临复杂的情况。你很可能发现默认的存储引擎并没有提供你需要的一个特性,比如事务,或者你需要比MyISAM的表锁定更细粒度的读写锁定。
因为你可以在表级别来选择存储引擎,因此你需要对如何使用每个表以及每个表中存的数据有一个清楚的认识。它不仅可以帮助你对于整个应用有一个比较好的整体理解,同时也可以对它的增长规模有一个估计。借助于这些信息,你可开始决定利用哪些存储引擎来完成这些任务了。
注:对于不同的表使用不同的存储引擎并不是很必要。如果你可以为所有的表使用同一个存储引擎来完成既定的任务,那么你将会发现你后面的工作要简单很多。
存储引擎选择的考查点
尽管许多因素都可以对存储引擎的选择造成影响,它通常还是可以归结为一些很基本的考查点。下面列出就是一些主要的考查点:
事务
如果你的需要事务,那么InnoDB是最稳定、并且集成度比较好的经过验证的选择。但是随着时间的推进,我们也将会看到许多更有竞争力的事务型引擎出现。如果不需要事务,而只是执行一些基本的查询和插入操作的话,MyISAM是一个比较好的选择。有时一个应用的一些特定的组件(比如日志)可能会归入这类应用。
并发
开发性需求的最好的衡量标准是你的工作量。如果你只量需要插入和写操作的并发性的话,不管你相信不相信,MyISAM是一个很不错的选择。如果你需要许多操作混合执行而互不影响的话,一个支持行锁的引擎将会是比较不错的选择。
备份
对于常规备份的需求也可能成为影响你的表选择的一个因素。如果你的服务器可以定时的关闭来备份的话,所有的存储引擎在处理上基本都差不多。但是如果你需要执行一个线上备份的话,选择就不是那么清晰了。第11章将会针对这个话题进行更详细的描述。但是需要记住一点,如果选用了多种存储引擎的话,将会增大备份和服务器调优的复杂性。
故障恢复
如果你有很多的数据,你需要很严肃地考虑它需要多久从一个故障中恢复。MyISAM表相对于InnoDB表来说,一般更容易损坏,并且需要花更多的时间来恢复。事实上这是为什么很多在即使不需要事务的时候也仍然选择InnoDB的原因。
特殊功能
最后,你有时可能会发现一个应用依赖于一些特定的功能或者优化,而这些优化可能只有一些MySQL的存储引擎提供。比如,许多应用依赖于簇索引的优化。在这个时候,你的选择就只有InnoDB和solidDB了。另一方面来说,只有MyISAM支持全文检索。如果一个存储引擎只符合其中的一些条件,而不符合其他的,你就需要妥协或者找到一个更聪明的设计方案了。你可能会经常遇到一种存储引擎只符合你的众多需求中的一些的情况
表的存储引擎转换
将一个表从一种存储引擎转换成另外一种有许多种方法,每一种都有它各自的优缺点。在下面的章节中我们将来详细介绍三种更大众的方法。
修改表
最简单的办法莫过于直接使用ALTER TABLE命令。下面的命令可以将mytable表转换为Falcon:
这个语法对于所有的存储引擎都是有效的,但是这里有一个陷阱:它可能会需要很长的时间。MySQL将会执行一个行到行的拷贝,将旧表的数据拷贝到新表中去。这个段时间里,你可能会将整个服务器的磁盘IO用尽,并且在这个过程中旧表是处于锁定状态的。因此,如果你需要在一个使用率很高的表上进行这个操作需要额外的小心。当然,你也可以使用下面讨论的其他方法中的一个,它们都会先拷贝一份原表。
当你将一个表的存储引擎从一种转换成另外一种时,任何针对原存储引擎的特性都会被丢弃。举个例子来说,如果你把一个InnoDB表转换成MyISAM,然后再转换回来,那么你将会发现InnoDB表上定义的所有外键约束都没有了。
1.5.19.2. 导出和导入
为了在整个转换过程中得到更大的控制权,你可以选择利用mysqldump工具先将表里的数据导出为文本文件。当你将表导出之后,你可简单地修改一下导出文件使得CREATE TABLE语句中的存储引擎变成你需要的。注意一定要将表名也修改了,因为同一个数据库里不可能有同名的表,即使它们是不同的类型。另外 mysqldump默认会导出一个DROP TABLE命令,因此如果你不小心的话,你可能就会丢失数据。
1.5.19.3. CREATE和SELECT
第三种方法是在前两种之间的一个融合,同时具有第一种的速度和第二种的安全性。与第二种导出整个表并且将它整个转换不同,第三种方案采用先建一张表,然后利用MySQL的INSERT…SELECT语法来填充它,如下所示:
如果你的数据不是很多的话,这个方案将会工作地很好;但是如果你有很多数据的话,比较有效的方法是增量式填充,将整个转换分成多个事务块来执行,这样子可以避免重做日志变得很大。假如id是主键,可以利用反复执行下面的命令来将表中的数据拷贝到新表中去(每次都增大x和y):
在这个过程完成之后,你将有拥有两张表,一个是原表,你可以在不再需要它时将它drop掉;另外一个是新表,它现在已经被完全的填充。如果需要防止数据的不一致拷贝将记得将原表锁定。