innodb 多版本并发控制原理详解(三)
(2011-09-19 09:36:20)
标签:
innodbmvcc控制原理详解杂谈 |
4.1 为什么select count(*)在myisam表上很快,而在Innodb的表上很慢?
因为innodb采用了MVCC技术,对于相同的行,可能同时存在多个版本,innodb必须根据查询的时间来过滤掉一些行,才能得出结果,必然要执行全表扫描,而全表扫描是非常耗时的.对于myisam的表,任何行都只有一个版本,mysql甚至不需要扫描就可以直接返回精确的统计结果,我们用explain也可以看到,对于myisam的表,执行select count(*)的时候,mysql显示” Select tables optimized away”,查询直接被优化了;而对于innodb的表,可能是全表扫描,也可能是”using index”,总之,速度肯定会比myisam的表慢很多.
4.2 我的数据库只是频繁更新,没有插入新数据,但是为什么表空间占用会越来越大?
如果你在数据库中执行了大事务, innodb就会把被修改数据的前映像存放到称为回滚段的公共表空间中,而且对于索引和表中的行的多个版本,如果innodb来不及purge,或者这些行因为要提供一致读而不能被purge,就会占用越来越多的空间,甚至有可能短时间撑爆你的硬盘.所以应用程序中需要合理控制事务的大小.
4.3 能禁用MVCC吗?
禁用MVCC可以降低innodb引擎的开销,而同时innodb又可以支持外键约束,可以实现自动恢复.MVCC本身不支持read uncommitted等级,所以可以通过设置transaction_isolation = read uncommitted 来禁用MVCC.但是任何改变innodb默认隔离等级的操作,都会起到innodb_locks_unsafe_for_binlog=off类似的效果,这会导致诸如insert into t select * from t_src 之类的语句不再给源表t_src加锁,也不再使用innodb的间隙锁,从而产生幻读,直接导致binlog中记录的sql语句不能正确的串行化,从而主从数据库的数据不再一致,而且基于binlog的增量备份也不再有效.所以除非不需要记录binlog,否则别这么做.当然我们可以这样做来优化从库的性能,因为从库不需要记录binlog.
4.4 何时使用char类型,何时使用varchar类型的列?
在使用myisam引擎的情况下,定长表虽然可能占用较多的存储空间,但是它会加快检索和全表扫描的速度,此时适合选用char的列,而对于表中的变长的列,可以采用分表的方法把变长的列拆分出去,提高定长表的检索性能.而如果使用的是innodb的引擎,由于innodb的mvcc策略的实施,char数据类型相对于varchar类型几乎没有任何优势,反而varchar列可能节省更多的存储空间,建议使用varchar数据类型.