MySQL的Innodb和myisam储存引擎(持续更新)

MySQL存储引擎的问题一直在面试的中频繁出现,理解MySQL的存储引擎的工作原理有助于在使用MySQL的过程中对查询原理理解更加深刻。

innodb:目前MySQL的默认存储引擎,也是使用最为广泛的存储引擎,特点:

  • 支持事务,支持外键,一致性非锁定读,行级锁的设定

    • 事务:一组原子性的操作,这组操作要么全部发生并完成,要么全部都不发生。事务把数据库从一种一致性状态转换为另一种一致性状态。
      • 事务的特性:事务具有ACID四种特性,即原子性、一致性、隔离性、持久性
        • 原子性(A):只一个不可分割的操作,要么全部正确执行,要么全部都不执行。
        • 一致性(C): 指事务从开始到结束后,数据库的完整性约束没有被破坏。
          • 完整性约束:用于确定关系型数据库里面数据的完整性和一致性。
        • 隔离性(I):每个读写事务之间是分开的,在事务提交前对其他事务是不可见的。
        • 持久性(D):指事务一旦提交,其改变结果就是永久性的,即使宕机也能恢复。
    • 外键:用于与其他表建立连接,一个表的外键有可能是另外一个表的主键,所以在删除时需要做一下确认。
    • 一致性非锁定读:是innodb通过多版本控制的方式读取当前执行时间数据库中的数据,如果被读的数据行被加了排它锁,在读取该行数据时并不会等待数据的释放,而是读取改行的一个快照数据。
    • 行级锁的设定:行锁大幅度提高了多用户并发操作的性能。但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的
  • innodb存储引擎采用聚集的方式存储,因此每张表的存储顺序都是按主键的顺序存储的。如果没有为表指定主键,那么innodb会为每一行生成一个6字节的ROWID并以此作为主键。想要理解聚集的存储方式可以参考理解InnoDB的聚集索引

  • innodb存储引擎通过MVCC(多版本并发控制)获得高并发性,并提供了插入缓冲、二次写、自适应hash索引和预读等高性能、高可用功能。

    • MVCC多版本并发控制:提供了一致性读不加锁的重要特性,这样一致性读不会阻塞更新,从而提升了数据库的性能。更多关于MVCC机制可以参考InnoDB的MVCC机制
    • 插入缓冲:Insert Buffer 用于非聚集索引的插入和更新操作。先判断插入的非聚集索引是否在缓存池中,如果在则直接插入,否则插入到 Insert Buffer 对象里。再以一定的频率进行 Insert Buffer 和辅助索引叶子节点的 merge 操作,将多次插入合并到一个操作中,提高对非聚集索引的插入性能。
      • 使用插入缓冲的两个条件:(1)索引是辅助索引;(2)索引不唯一。如果索引唯一还要去查找索引页进行检查唯一性,就失去了 Insert Buffer 离散插入的性能
    • 二次写:如果数据库发生宕机时,可以通过重做日志对该页进行恢复,但是如果该页本身已经损坏了,进行重做恢复是没有意义的。因此引入了"二次写"方案,提高数据页的稳定性。
    • 自适应哈希(hash)索引:InnoDB 会监控对表上各个索引页的查询,如果观察到通过哈希索引可以带来性能提升,则自动建立哈希索引。自适应哈希索引通过缓存池的 B+ 树页构造而来,因此建立速度很快。
    • 预读机制:就是发起一个I/O请求,异步地在缓冲池中预先回迁若干个页面(预计很快就会需要的页面),这些请求在一个范围内引入所有页面。
  • innodb存储引擎默认的隔离级别为重复性读,并采用间歇锁来避免幻读。

    • 隔离级别:SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的改变哪些是可见的,哪些是不可见。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
      • Read Uncommitted(读取未提交内容)
        在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)
      • Read Committed(读取提交内容)
        这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的改变。这种隔离级别也支持所谓的不可重复读(Nonrepeatable Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。
      • Repeatable Read(可重读)
        这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影”行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
      • erializable(可串行化)
        这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。
      • 这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如: 脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。

myisam:在MySQL 5.1 及之前的版本,MyISAM是默认引擎。MyISAM提供的大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM并不支持事务以及提供行级锁,并且一个毫无疑问的缺陷是崩溃后无法安全恢复。

  • 不支持事务,表级锁的设计,支持全文索引(innodb5.6版本后支持),MyISAM允许没有主键的表存在
    • 表级锁:只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。
    • 全文索引:如果希望通过关键词的匹配来进行查询过滤,那么就需要基于相似度的查询,而不是原来的精确值的比较,全文索引就是为这种场景所设计的
  • myisam的存储结构会在磁盘上分我三个文件进行存储,分别是:.frm文件用于保存表格定义;MYD文件用于保存数据;MYI文件用于存储索引
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章