日期:2014-05-16  浏览次数:20467 次

mysql DB引擎myisam与innodB

功能上:
InnoDB支持事务安全、Mysq唯一支持外键的存储引擎。使用要使用事务或者外键,InnoDB成为不二的选择。
但同时InnoDB提供了两种自动提交和手动提交两种选择(SET  AUTOCOMMIT=0设置),根据文档所述,自动提交的性能很差,所有的修改操作和非自动提交都有200多倍的性能差距!

性能上:
1、InnoDB采用记录锁同步操作,MyISAM采用的是表锁。
正是因为这个本质的区别,决定了在涉及有频繁的读写操作(并发)时,InnoDB的性能要高于MyISAM,所以我们在一般情况下都支持使用InnoDB而非MyISAM,以降低删除更新频繁的锁表。InnoDB的引擎在大量更改的更改操作环境有更好的表现。
同时,由于MyISAM引擎采用表锁,所以在读写压力比较大下,由于写操作锁会阻塞所有的读取锁(MyISAM写操作的优先级高于读取操作),所以此时表的读取操作必须等待,造成效率低下。
而InnoDB的引擎对于读取操作几乎不加锁,如果此记录正在被写,才会阻塞此记录相关的读取操作和写入操作(行锁)。


2、InnoDB读能力上的优势。
winfer提到InnoDB是真正的data cache,MyISAM是key  buffer,再怎么都要读硬盘的数据。
这点上与文档Mysql 4.0 查询cache差强人意有出入。不知道5.0的后cache是否有改善。
文档中指出,使用Cache时,同样是有成本的,特别是对查询语句,成本还比较高,单条查询SQL的使用Cache成本大约是比不是使用Cache的成本高40%,这个成本应该来自MySQL要消耗将结果保存到Cache和淘汰出Cache的时间。它同时指出MySQL的查询Cache淘汰策略近乎弱智,后续版本是否还有这个问题有待后续的研究。
(By nicola:winfer提到的 data  cache和文档中的查询cache指的是不同的内容,一个缓存的是数据页,一个是查询结果。Winfer指的是将数据文件的一部分放在内存中以提高查询效率,innodb有这样的机制,可以将包括索引和数据都在内的数据文件页缓存起来,myisam只能缓存索引。文档中的查询cache是将之前已经进行过的查询的结果存放在内存中,当下次同样的查询请求过来的时候可以直接将内存中的结果返回。Mysql的查询cache是按表为单位进行的,当一个表的记录发生了改变,有关该表的查询cache就通通失效了,因此很容易发生淘汰,作用比较有限,也就是文档中提到的“弱智”的地方。)
(By winfer:嗯,文档中提到的查询  cache 是指对某个sql语句的查询结果在内存(查询  cache)中保存起来,并用该sql语句的hash值与之对应,当一摸一样的sql(HASH值一致)再次被查询的时候对重用这个查询cache中的结果。当正如nicola说的,只要结果集中的某个记录有变化的时候这个cache中保存的结果就失效了。所以mysql  的这个查询cache 在更新量比较大的数据库中往往只会降低性能。另外 查询cache 是集成在mysql 的框架中的,在存储引擎之上。这里要跟 myisam 与  innodb 的数据buffer 区分开。)

安全上:
adward提到MyISAM经常坏表,文档中指出MyISAM引擎的故障主要就是索引错误(数据文件和索引不一致),原来出现这种错误,文档也总结了三个原因:(1)在联机状态kill的mysqld;(2)不锁表,在mysqld运行的时候拷贝,读写,备份数据文件;(3)不锁表,在mysqld运行的时候,使用外部程序影响数据文件,比如用myisamchk在联机状态下修复。
(这里有个疑问,adward提到MyISAM经常坏表,是否都是由于这些原因引来的?)
而相反,正如winfer提到的,InnoDB的崩溃处理(redo log,undo log)给我们提供了比较完整的解决方案。


适用MyISAM的情况:
纯插入(特别是顺序操作)、纯读取应用,MyISAM要比InnoDB好。
所以正如benny和nicola所述,按时间建表或者日志流水DB,适用MyISAM。
因为在MyISAM数据文件没有空洞时(删除记录会产生一个没有使用的记录区),插入记录操作没有进行锁表操,所以在纯插入MyISAM引擎不用加入写锁锁定表。
同时一般认为MyISAM引擎利于检索,因为查询操作使用读取锁可以并发。
《且将新火试新茶》这份文档的测试主要还是针对Mysql  4.0的,内容作参考用。
同时有个疑问,不知道我们使用的Mysql前是否也经过类似测试并有测试数据说明它具有较好的性能呢?