zoukankan      html  css  js  c++  java
  • MySQL数据库系列(三)- MySQL常用引擎MyISAM和InnoDB区别详解

    概述

    InnoDB:在MySQL 5.5及之后的版本,InnoDB是MySQL默认的事务型引擎,也是最重要和使用最广泛的存储引擎。它被设计成为大量的短期事务,短期事务大部分情况下是正常提交的,很少被回滚。InnoDB的性能与自动崩溃恢复的特性,使得它在非事务存储需求中也很流行。除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎。InnoDB是支持事务安全的引擎,支持外键、行锁、事务是他的最大特点。如果有大量的update和insert,建议使用InnoDB,特别是针对多个并发和QPS较高的情况。

    MyISAM:它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法。在MySQL 5.1及之前的版本,MyISAM是默认引擎。MyISAM提供的大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM并不支持事务以及行级锁,而且一个毫无疑问的缺陷是崩溃后无法安全恢复。正是由于MyISAM引擎的缘故,即使MySQL支持事务已经很长时间了,在很多人的概念中MySQL还是非事务型数据库。尽管这样,它并不是一无是处的。对于只读的数据,或者表比较小,可以忍受修复操作,则依然可以使用MyISAM(但请不要默认使用MyISAM,而是应该默认使用InnoDB)

    一、MyISAM 和 InnoDB 的区别

    1、存储结构和空间差异

    1)、 存储结构
    MyISAM:每个MyISAM在磁盘上存储成三个文件。分别为:表定义文件、数据文件、索引文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。.frm文件存储表定义。数据文件的扩展名为.MYD (MYData)。索引文件的扩展名是.MYI (MYIndex)。
    InnoDB:所有的表都保存在同一个数据文件中(也可能是多个文件,或者是独立的表空间文件),InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。
    2)、 存储空间
    MyISAM: MyISAM支持支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。当表在创建之后并导入数据之后,不会再进行修改操作,可以使用压缩表,极大的减少磁盘的空间占用。
    InnoDB: 需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。

    2、表锁差异

    MyISAM:只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。也可以通过lock table命令来锁表,这样操作主要是可以模仿事务,但是消耗非常大,一般只在实验演示中使用。

    InnoDB :支持事务和行级锁,是innodb的最大特色。

    事务的ACID属性:atomicity,consistent,isolation,durable。

    并发事务带来的几个问题:更新丢失,脏读,不可重复读,幻读。

    事务隔离级别:未提交读(Read uncommitted),已提交读(Read committed),可重复读(Repeatable read),可序列化(Serializable)

    四种隔离级别的比较 

     

    查看mysql的默认事务隔离级别show global variables like ‘tx_isolation’; ”

    (root@3307-08:33:25:)[(none)]> show global variables like 'tx_isolation';
    +---------------+-----------------+
    | Variable_name | Value           |
    +---------------+-----------------+
    | tx_isolation  | REPEATABLE-READ |
    +---------------+-----------------+
    1 row in set (0.00 sec) 

    Innodb的行锁模式有以下几种:共享锁,排他锁,意向共享锁(表锁),意向排他锁(表锁),间隙锁。
    注意:当语句没有使用索引,innodb不能确定操作的行,这个时候就使用的意向锁,也就是表锁

    关于死锁:
    什么是死锁?当两个事务都需要获得对方持有的排他锁才能完成事务,这样就导致了循环锁等待,也就是常见的死锁类型。

    解决死锁的方法:
    1、 数据库参数
    2、 应用中尽量约定程序读取表的顺序一样
    3、 应用中处理一个表时,尽量对处理的顺序排序
    4、 调整事务隔离级别(避免两个事务同时操作一行不存在的数据,容易发生死锁)

    3、索引差异

    我们都知道InnoDB和MyISAM都是B+数的结构,但是它们的实现有点不一样,MyISAM的查询性能会比InnoDB强,InnoDB是聚簇索引(叶子节点存数据),MyISAM是非聚簇索引(叶子节点存指针),如图:

     具体信息描述:

    1)、关于自动增长
    myisam引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,他可以根据前面几列进行排序后递增。
    innodb引擎的自动增长咧必须是索引,如果是组合索引也必须是组合索引的第一列。
    2)、关于主键
    myisam允许没有任何索引和主键的表存在,
    myisam的索引都是保存行的地址。
    innodb引擎如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见)
    innodb的数据是主索引的一部分,附加索引保存的是主索引的值。
    3)、关于count()函数
    myisam保存有表的总行数,如果select count(*) from table;会直接取出出该值
    innodb没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre 条件后,myisam和innodb处理的方式都一样。
    4)、全文索引
    myisam支持 FULLTEXT类型的全文索引
    innodb不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好,而且在5.7版本以后的innodb支持全文索引了。(sphinx 是一个开源软件,提供多种语言的API接口,可以优化mysql的各种查询)
    5)、delete from table
    使用这条命令时,innodb不会从新建立表,而是一条一条的删除数据,在innodb上如果要清空保存有大量数据的表,最好不要使用这个命令。(推荐使用truncate table,不过需要用户有drop此表的权限)
    6)、索引保存位置
    myisam的索引以表名+.MYI文件分别保存。
    innodb的索引和数据一起保存在表空间里

    7)AUTO_INCREMENT MyISAM:可以和其他字段一起建立联合索引。引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,他可以根据前面几列进行排序后递增。
    InnoDB:InnoDB中必须包含只有该字段的索引。引擎的自动增长列必须是索引,如果是组合索引也必须是组合索引的第一列。

    4、数据库文件差异

    MyISAM :
    myisam属于堆表,myisam在磁盘存储上有三个文件,每个文件名以表名开头,扩展名指出文件类型。

    1).frm 用于存储表的定义
    2).MYD 用于存放数据
    3).MYI 用于存放表索引

    myisam表还支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。

    InnoDB :
    innodb属于索引组织表,innodb有两种存储方式,共享表空间存储和多表空间存储

    两种存储方式的表结构和myisam一样,以表名开头,扩展名是.frm。

    如果使用共享表空间,那么所有表的数据文件和索引文件都保存在一个表空间里,一个表空间可以有多个文件,通过innodb_data_file_path和innodb_data_home_dir参数设置共享表空间的位置和名字,一般共享表空间的名字叫ibdata1-n。

    如果使用独立表空间(多表空间),那么每个表都有一个表空间文件用于存储每个表的数据和索引,文件名以表名开头,以.ibd为扩展名。

    详细解释请查看:https://www.cnblogs.com/easonscx/p/12598100.html

    5、其他差异

    1).可移植性、备份及恢复
    MyISAM:数据是以文件的形式存储,所以在跨平台的数据转移中会很方便。在备份和恢复时可单独针对某个表进行操作。
    InnoDB:免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了。
    2).事务支持
    MyISAM:强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持。
    InnoDB:提供事务支持事务,外部键等高级数据库功能。 具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。
    3).表主键
    MyISAM:允许没有任何索引和主键的表存在,索引都是保存行的地址。
    InnoDB:如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值。
    4).表的具体行数
    MyISAM: 保存有表的总行数,如果select count() from table;会直接取出出该值。
    InnoDB: 没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样。
    5).CRUD操作
    MyISAM:如果执行大量的SELECT,MyISAM是更好的选择。
    InnoDB:如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。
    6). 外键

    MyISAM不支持外键,InnoDB支持外键。

    7)数据库恢复

    MyISAM崩溃后无法安全恢复,InnoDB支持崩溃后的安全恢复。
    InnoDB实现了一套完善的崩溃恢复机制,保证在任何状态下(包括在崩溃恢复状态下)数据库挂了,都能正常恢复。

    8).缓存机制不同

    MyISAM仅缓存索引信息,而不缓存实际的数据信息。
    InnoDB不仅缓存索引信息,还会缓存数据信息。其将数据文件按页读取到缓冲池,然后按最近最少使用的算法来更新数据。

    二、使用中如何选择

    1、innodb引擎的特点
    1).支持事务
    2).支持行锁,并发性能好
    3).CPU及内存缓存页优化使得资源利用率高

    2、MYISAM特点
    1).单条sql语句执行快
    2).表锁
    3).不支持事务
    依据上述特点,我们在使用MySQL数据库时,选择使用引擎建议参照如下描述
    使用INNODB场景有两个,满足一个即可使用
    1 需要事务;
    2 并发量大,写频繁或者有复杂sql长时间执行;

    使用Myisam场景有两个,满足一个即可使用
    1 并发量小时一律使用myisam;
    2 并发量大,少复杂查询,读多写少,锁竞争不激烈时使用MYISAM;

    但是,由于开发人员水平参差不齐,在使用myisam时,如果执行了复杂sql,join表数量多时可能会导致表长时间被锁,所以互联网项目一律使用InnoDB;

    三、开发的注意事项

    1、可以用 show create table tablename 命令看表的引擎类型。

    2、对不支持事务的表做start/commit操作没有任何效果,在执行commit前已经提交。

    3、可以执行以下命令来切换非事务表到事务(数据不会丢失),innodb表比myisam表更安全:alter table tablename type=innodb;或者使用 alter table tablename engine = innodb;

    4、默认innodb是开启自动提交的,如果你按照myisam的使用方法来编写代码页不会存在错误,只是性能会很低。如何在编写代码时候提高数据库性能呢?

    5、尽量将多个语句绑到一个事务中,进行提交,避免多次提交导致的数据库开销。

    6、在一个事务获得排他锁或者意向排他锁以后,如果后面还有需要处理的sql语句,在这两条或者多条sql语句之间程序应尽量少的进行逻辑运算和处理,减少锁的时间。

    7、尽量避免死锁

    8、sql语句如果有where子句一定要使用索引,尽量避免获取意向排他锁。

    9、针对我们自己的数据库环境,日志系统是直插入,不修改的,所以我们使用混合引擎方式,ZION_LOG_DB照旧使用myisam存储引擎,只有ZION_GAME_DB,ZION_LOGIN_DB,DAUM_BILLING使用Innodb引擎。

     ---------------------------------------------书山有路勤为径,学海无涯苦作舟--------------------------------------------------------

  • 相关阅读:
    iview正在加载和关闭加载
    vue实现input输入框只能输入中文
    vue添加遮罩
    JSONP的实现原理
    vue-resource 实现 get, post, jsonp请求
    vue实例的生命周期
    IDE更新索引
    org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
    springmvc过滤的静态资源不起作用
    mybatis返回集合类型为map时
  • 原文地址:https://www.cnblogs.com/easonscx/p/12598092.html
Copyright © 2011-2022 走看看