MySql的多存储引擎架构, 默认的引擎InnoDB与 MYISAM的区别(滴滴 阿里)

一、存储引擎是什么?html

  MySQL中的数据用各类不一样的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不一样的存储机制、索引技巧、锁定水平而且最终提供普遍的不一样的功能和能力。经过选择不一样的技术,你可以得到额外的速度或者功能,从而改善你的应用的总体功能。这些不一样的技术以及配套的相关功能在MySQL中被称做存储引擎(也称做表类型)。MySql默认配置了许多不一样的存储引擎,能够预先设置或者在MySql服务器中启用。mysql

  二、MYSQL支持的数据引擎git

  MyISAM最大的特色是不支持事务默认fulltext 全文索引;(阿里面试)默认的MySQL插件式存储引擎,它是在Web、数据仓储和其余应用环境下最常使用的存储引擎之一。github

  InnoDB:最大的特色是支持事务处理默认B+ Tree索引;具备众多特性,包括ACID事务支持,InnoDB默认加锁方式是next-key 锁面试

  BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其余事务特性。sql

  Memory:默认hash索引;将全部数据保存在RAM中,在须要快速查找引用和其余相似数据的环境下,可提供极快的访问。数据库

  Merge:容许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一块儿,并做为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。编程

  Archive:为大量不多引用的历史、归档、或安全审计信息的存储和检索提供了完美的解决方案。api

  Federated:可以将多个分离的MySQL服务器连接起来,从多个物理服务器建立一个逻辑数据库。十分适合于分布式环境或数据集市环境。缓存

  Cluster/NDB:MySQL的簇式数据库引擎,尤为适合于具备高性能查找要求的应用程序,这类查找需求还要求具备最高的正常工做时间和可用性。

  Other:其余存储引擎包括CSV(引用由逗号隔开的用做数据库表的文件),Blackhole(用于临时禁止对数据库的应用程序输入),以及Example引擎(可为快速建立定制的插件式存储引擎提供帮助)。

 三、   MyISAM引擎与InnoDB的区别(百度面试):

一、MyIASM是非事务安全的,不支持事务,而InnoDB是事务安全的,支持事务这是最重要的区别(百度面试)

二、MyIASM锁的粒度是表级的,而InnoDB支持行级锁

三、MyIASM支持全文类型索引,而InnoDB不支持全文索引

四、MyIASM相对简单,效率上要优于InnoDB,小型应用能够考虑使用MyIASM

五、MyIASM表保存成文件形式,跨平台使用更加方便 

Innodb引擎 

  Mysql中默认的是MyISAM数据引擎,惋惜此引擎不支持事务处理,咱们须要将默认的数据引擎改成InnoDB。其中InnoDB和BerkeleyDB支持事务处理,只是默认的状况下都是被disable的。全部的引擎里面,InnoDB性能最强大,算是商业级的。启动InnoDB引擎的方法以下

  1)关闭mysql的服务

  2)修改my.ini

  将default-storage-engine=INNODB前的注释(#)去掉

  将skip-innodb这行注释(加上#)

  3)保存后重启mysql服务 

Innodb引擎提供了对数据库ACID事务的支持,而且实现了SQL标准的四种隔离级别。该引擎还提供了行级锁和外键约束, 

 其实innodb支持三种锁:Mysql间隙锁最大的特色是在repeatable read隔离级别下,使用间隙锁来防止幻读。(百度面试)

参考:Mysql 间隙锁原理,以及Repeatable Read隔离级别下能够防止幻读原理(百度)

(a)记录锁(也叫行锁),

(b)间隙锁,

(c)next-key锁通通属于排他锁。

行锁
记录锁其实很好理解,对表中的记录加锁,叫作记录锁,简称行锁。

生活中的间隙锁
编程的思想源于生活,生活中的例子能帮助咱们更好的理解一些编程中的思想。
生活中排队的场景,小明,小红,小花三我的依次站成一排,此时,如何让新来的小刚不能站在小红旁边,这时候只要将小红和她前面的小明之间的空隙封锁,将小红和她后面的小花之间的空隙封锁,那么小刚就不能站到小红的旁边。
这里的小红,小明,小花,小刚就是数据库的一条条记录。
他们之间的空隙也就是间隙,而封锁他们之间距离的锁,叫作间隙锁。 

next-key锁
next-key锁其实包含了记录锁和间隙锁,即锁定一个范围,而且锁定记录自己InnoDB默认加锁方式是next-key 锁。

 

MyIASM是MySQL默认的引擎,可是它没有提供对数据库事务的支持,也不支持行级锁和外键,所以当INSERT(插入)或UPDATE(更新)数据时即写操做须要锁定整个表,效率便会低一些。不过和Innodb不一样,MyIASM中存储了表的行数,因而SELECT COUNT(*) FROM TABLE时只须要直接读取已经保存好的值而不须要进行全表扫描。若是表的读操做远远多于写操做且不须要数据库事务的支持,那么MyIASM也是很好的选择。

应用场景:

一、MyIASM管理非事务表,提供高速存储和检索以及全文搜索能力,若是再应用中执行大量select操做,应该选择MyIASM
二、InnoDB用于事务处理,具备ACID事务支持等特性,若是在应用中执行大量insert和update操做,应该选择InnoDB

  这些区别可以影响应用程序的性能和功能,所以你必须针对业务类型来选择合适的引擎,才能最大的发挥MySQL的性能优点。 

 

 

 

支持多种存储引擎是众所周知的MySQL特性,也是MySQL架构的关键优点之一。若是可以理解MySQL Server与存储引擎之间是怎样经过API交互的,将大大有利于理解MySQL的核心基础架构。本文将首先介绍MySQL的总体逻辑架构,而后分析MySQL的存储引擎API并介绍如何编写本身的MySQL存储引擎。

MySQL逻辑架构

MySQL做为一个大型的网络程序、数据管理系统,架构很是复杂。下图大体画出了其逻辑架构。

MySQL由如下几部分组成:

  1. 链接池组件。
  2. 管理服务和工具组件。
  3. SQL接口组件。
  4. 查询分析器组件。
  5. 优化器组件。
  6. 缓冲(Cache)组件。
  7. 插件式存储引擎。
  8. 物理文件。

Connectors

MySQL首先是一个网络程序,其在TCP之上定义了本身的应用层协议。因此要使用MySQL,咱们能够编写代码,跟MySQL Server创建TCP链接,以后按照其定义好的协议进行交互。固然这样比较麻烦,比较方便的办法是调用SDK,好比Native C API、JDBC、PHP等各语言MySQL Connector,或者经过ODBC。但经过SDK来访问MySQL,本质上仍是在TCP链接上经过MySQL协议跟MySQL进行交互。

Connection Management

每个基于TCP的网络服务都须要管理客户端连接,MySQL也不例外。MySQL会为每个链接绑定一个线程,以后这个链接上的全部查询都在这个线程中执行。为了不频繁建立和销毁线程带来开销,MySQL一般会缓存线程或者使用线程池,从而避免频繁的建立和销毁线程。

客户端链接到MySQL后,在使用MySQL的功能以前,须要进行认证,认证基于用户名、主机名、密码。若是用了SSL或者TLS的方式进行链接,还会进行证书认证。

SQL Interface

MySQL支持DML(数据操做语言)、DDL(数据定义语言)、存储过程、视图、触发器、自定义函数等多种SQL语言接口。

Parser

MySQL会解析SQL查询,并为其建立语法树,并根据数据字典丰富查询语法树,会验证该客户端是否具备执行该查询的权限。建立好语法树后,MySQL还会对SQl查询进行语法上的优化,进行查询重写。

Optimizer

语法解析和查询重写以后,MySQL会根据语法树和数据的统计信息对SQL进行优化,包括决定表的读取顺序、选择合适的索引等,最终生成SQL的具体执行步骤。这些具体的执行步骤里真正的数据操做都是经过预先定义好的存储引擎API来进行的,与具体的存储引擎实现无关。

Caches & Buffers

MySQL内部维持着一些Cache和Buffer,好比Query Cache用来缓存一条Select语句的执行结果,若是可以在其中找到对应的查询结果,那么就没必要再进行查询解析、优化和执行的整个过程了。

Pluggable Storage Engine

存储引擎的具体实现,这些存储引擎都实现了MySQl定义好的存储引擎API的部分或者所有。MySQL能够动态安装或移除存储引擎,能够有多种存储引擎同时存在,能够为每一个Table设置不一样的存储引擎。存储引擎负责在文件系统之上,管理表的数据、索引的实际内容,同时也会管理运行时的Cache、Buffer、事务、Log等数据和功能。

MySQL 5.7.11默认支持的存储引擎以下:

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES | YES | YES | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 

File System

全部的数据,数据库、表的定义,表的每一行的内容,索引,都是存在文件系统上,以文件的方式存在的。固然有些存储引擎好比InnoDB,也支持不使用文件系统直接管理裸设备,但现代文件系统的实现使得这样作没有必要了。

在文件系统之下,可使用本地磁盘,可使用DAS、NAS、SAN等各类存储系统。

存储引擎API

MySQL定义了一系列存储引擎API,以支持插件式存储引擎架构。API以Handler类的虚函数的方式存在,可在代码库下的./sql/handler.h中查看详细信息,可在handler类的注释中看到描述:

/** The handler class is the interface for dynamically loadable storage engines. Do not add ifdefs and take care when adding or changing virtual functions to avoid vtable confusion Functions in this class accept and return table columns data. Two data representation formats are used: 1. TableRecordFormat - Used to pass [partial] table records to/from storage engine 2. KeyTupleFormat - used to pass index search tuples (aka "keys") to storage engine. See opt_range.cc for description of this format. TableRecordFormat ================= [Warning: this description is work in progress and may be incomplete] The table record is stored in a fixed-size buffer: record: null_bytes, column1_data, column2_data, ... //篇幅缘由,略去部份内容。 */ class handler :public Sql_alloc { //篇幅缘由,不列出具体代码。读者可直接在源码文件./sql/handler.h中找到具体内容。 }

下面我将分类描述部分存储引擎API。

建立、打开和关闭表

经过函数create来建立一个table:

/**  *name:要建立的表的名字  *from:一个TABLE类型的结构,要建立的表的定义,跟MySQL Server已经建立好的tablename.frm文件内容是匹配的  *info:一个HA_CREATE_INFO类型的结构,包含了客户端输入的CREATE TABLE语句的信息 */ int create(const char *name, TABLE *form, HA_CREATE_INFO *info);

经过函数open来打开一个table:

/** mode包含如下两种 O_RDONLY - Open read only O_RDWR - Open read/write */ int open(const char *name, int mode, int test_if_locked);

经过函数close来关闭一个table:

int close(void);

对表加锁

当客户端调用LOCK TABLE时,经过external_lock函数加锁:

int ha_example::external_lock(THD *thd, int lock_type)

全表扫描

//初始化全表扫描 virtual int rnd_init (bool scan); //从表中读取下一行 virtual int rnd_next (byte* buf);

经过索引访问table内容

//使用索引前调用该方法 int ha_foo::index_init(uint keynr, bool sorted) //使用索引后调用该方法 int ha_foo::index_end(uint keynr, bool sorted) //读取索引第一条内容 int ha_index_first(uchar * buf); //读取索引下一条内容 int ha_index_next(uchar * buf); //读取索引前一条内容 int ha_index_prev(uchar * buf); //读取索引最后一条内容 int ha_index_last(uchar * buf); //给定一个key基于索引读取内容 int index_read(uchar * buf, const uchar * key, uint key_len, enum ha_rkey_function find_flag)

事务处理

//开始一个事务 int my_handler::start_stmt(THD *thd, thr_lock_type lock_type) //回滚一个事务 int (*rollback)(THD *thd, bool all); //提交一个事务 int (*commit)(THD *thd, bool all);

如何编写本身的存储引擎

在MySQL的官方文档上,有对于编写本身的存储引擎的指导文档,连接以下

做为编写本身存储引擎的开始,你能够查看MySQL源码库中的一个EXAMPLE存储引擎,它实现了必需要实现的存储引擎API,能够经过复制它们做为编写咱们本身存储引擎的开始:

sed -e s/EXAMPLE/FOO/g -e s/example/foo/g ha_example.h > ha_foo.h
sed -e s/EXAMPLE/FOO/g -e s/example/foo/g ha_example.cc > ha_foo.cc
相关文章
相关标签/搜索