第1章 MySQL架构与历史

余生长醉 提交于 2020-02-09 19:54:34

MySQL最重要、最与众不同的特性是它的存储引擎架构,这种架构的设计将查询处理(Query Processing)及其他系统任务(Server Task)和数据的存储/提取相分离。这种处理和存储分离的设计可以在使用时根据性能、特性,以及其他需求来选择数据存储的方式

1.1 MySQL逻辑架构

MySQL服务器逻辑架构图

  • 最上层服务大多数系统都有,连接处理、授权认证、安全等等
  • 第二层包含MySQL的大多数核心功能
  • 第三层包含了存储引擎。存储引擎负责MySQL中数据的存储和提取
1.1.1 连接管理与安全性

每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,该线程只能轮流在某个CPU核心或者CPU中运行。服务器会负责缓存线程,因此不需要为每一个新建的连接创建或者销毁线程。
当客户端连接到MySQL服务器时,服务器需要对其进行认证。认证基于用户名、原始主机信息和密码。如果使用了安全套接字SSL)的方式连接,还可以使用X.059证书认证。一旦客户端连接成功,服务器会继续验证该客户端是否具有执行某个特定查询的权限(例如,是否允许客户端对world数据库的Country表执行SELECT语句)。

1.1.2 优化与执行

MySQL会解析查询,并创建内部数据结构,然后对其进行各种优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。
对于SELECT语句,在解析查询之前,服务器会先检查查询缓存

1.2 并发控制

1.2.1 读写锁

在处理并发读写时,可以通过实现一个由两种类型的锁组成的锁系统来解决问题。这两种类型的锁通常被称为共享锁(shared lock)和排他锁(exclusive lock),也叫读锁(read lock)和写锁(write lock)。
读锁是共享的,或者说是相互不阻塞的。多个客户在同一时刻读取同一个资源,而互不干扰。写锁则是排他的,也就是说一个写锁会阻塞其他的写锁和读锁

1.2.2 锁粒度

一种提高共享资源并发性的方式就是让锁定对象更有选择性。加锁需要消耗资源。所谓的锁策略,就是在锁的开销和数据的安全性之间寻求平衡,这种平衡当然也会影响到性能。
MySQL提供了多种选择,每种MySQL存储引擎都可以实现自己的锁策略和锁粒度

表锁

表锁是MySQL中最基本的锁策略,并且是开销最新的策略。它会锁定整张表。服务器会为ALTER TABLE之类的语句使用表锁,而忽略存储引擎的锁机制

行级锁

行级锁可以最大程度地支持并发处理(同时也带来了最大的锁开销)。众所周知,在InnoDB和XtraDB,以及其他一些存储引擎中实现了行级锁。行级锁只在存储引擎层实现,而MySQL服务器层没有实现。服务器层完全不了解存储引擎中的锁实现

1.3 事务

事务就是一组原子性的SQL查询,或者说一个独立的工作单元。事务内的语句,要么全部执行成功,要么全部执行失败。

事务的ACID
  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation)
  • 持久性(durability)
    一个实现了ACID的数据库,相比没有实现ACID的数据库,通常会需要更强的CPU处理能力、更大的内存和更多的磁盘空间。用户可以根据业务是否需要事务处理,来选择合适的存储引擎
1.3.1 隔离级别

在SQL标准中定义了四种隔离级别

  • READ UNCOMMITTED (未提交读),事务可以读取未提交的数据,这也被称为脏读(Dirty Read)
  • READ COMMITTED (提交读),会出现不可重复读
  • REPEATABLE READ (可重复读),解决脏读和不可重复读问题,但是会出现幻读问题
  • SERIALIZABLE(可串行化),解决幻读问题,会在读取的每一行数据上加锁,所以可能导致大量的超时和锁争用的问题。
  • 隔离级别
1.3.2 死锁

死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务试图以不同的顺序锁定资源时,就可能会产生死锁。多个事务同时锁定同一个资源时,也会产生死锁
为了解决这种问题,数据库系统实现了各种死锁检测和死锁超时机制。InnoDB处理死锁的方法是,将持有最少行排他锁的事务进行回滚

1.3.3 事务日志

事务日志可以帮助提高事务的效率。使用事务日志,存储引擎在修改表的数据时只需要想修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘
如果数据的修改已经记录到事务日志并从持久化,但数据本身还没有写回磁盘,此时系统崩溃,存储引擎在重启时能够自动恢复这部分修改的数据

1.3.4 MySQL中的事务

MySQL提供了两种事务型的存储引擎:InnoDB和NDB Cluster
MySQL默认采用自动提交模式。可以通过设置AUTOCOMMIT变量来启用或者禁用自动提交模式
MySQL可以通过执行SET TRANSACTION ISOLATION 命令来设置隔离级别

在事务中混合使用存储引擎

MySQL服务器层不管理事务,事务是由下层的存储引擎实现的。所以在同一个事务中,使用多种存储引擎是不可靠的

隐式和显式锁定

InnoDB采用的是两阶段锁定协议。在事务执行过程中,随时可以执行锁定,锁只有再执行COMMIT或者ROLLBACK的时候才会释放,并且所有的锁是在同一时刻被释放。
注:除了事务中禁用了AUTOCOMMIT,可以使用LOCK TABLES之外,其他任何时候都不要显式地执行LOCK TABLES,不管使用的是什么存储引擎

1.4 多版本并发控制

MVCC是行级锁的一个变种。是通过保存数据在某个时间点的快照来实现的。
InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存了行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本进行比较。
具体操作如下图:
InnoDB的MVCC
MVCC只在REPEATABLE READ和READ COMMITTED两个隔离级别下工作。其他两个隔离级别都和MVCC不兼容,因为READ COMMITED总是读取最新的数据行,而不是符合当前事务版本的数据行。而SERIALIZABLE则会对所有读取的行都加锁

1.5 MySQL的存储引擎

使用SHOW TABLE STATUS命令显示表的相关信息

1.5.1 InnoDB 存储引擎

InnoDB是MySQL的默认事务型引擎,被设计用来处理大量的短期(short-lived)事务,短期事务大部分情况是正常提交的,很少会被回滚。InnoDB的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中也很流行

InnoDB概览

InnoDB的数据存储在表空间中,表空间是由InnoDB管理的一个黑盒子,由一系列的数据文件组成。
InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。其默认级别是REPEATABLE READ(可重复读),并且通过间隙锁(next-key locking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插入
InnoDB表是基于聚簇索引建立的,聚簇索引对主键查询有很高的性能。不过它的二级索引中必须包含主键列,主键应当尽可能的小。InnoDB的存储格式是平台独立的,也就是说可以将数据和索引文件从Intel平台复制到PowerPC或者Sun SPARC平台。

1.5.2 MyISAM 存储引擎

MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM不支持事务和行级锁,而且有一个毫无疑问的缺陷就是崩溃后无法安全恢复。
如果表在创建并导入数据以后,不会再进行修改操作,那么这样的表或许适合采用MyISAM压缩表

1.5.3 MySQL内建的其他存储引擎

Archive引擎、Blackhole引擎、CSV引擎、Federated引擎、Memory引擎、Merge引擎、NDB集群引擎

1.5.4 第三方存储引擎

MySQL从2007年开始提供了插件式的存储引擎API
OLTP类引擎、面向列的存储引擎、社区存储引擎

1.5.5 选择合适的引擎

大部分情况下,InnoDB都是正确的选择。除非需要用到某些InnoDB不具备的特性,并且没有其他办法可以替代,否则都应该优先选择InnoDB引擎
如果要用到全文索引,建议优先考虑InnoDB加上Sphinx的组合,而不是MyISAM。
选择引擎时考虑的因素:事务、备份、崩溃恢复、特有的特性

1.5.6 转换表的引擎

三种方法:

  • ALTER TABLE,需要执行很长时间
  • 导出与导入,可以使用mysqldump工具将数据导出到文件,然后修改存储引擎选项
  • 创建与查询,综合前两种方法,用INSERT…SELECT语法导数据

1.6 MySQL时间线

版本3.23 —— 被认为是MySQL真正“诞生”的时刻
版本5.5 —— Oracle收购Sun以后发布的首个版本

1.7 MySQL的开发模式

现在Oracle为付费用户单独提供了一些服务器插件,而MySQL本身还是遵循开源模式

1.8 总结

MySQL拥有分层的架构。上层是服务器层的服务和查询执行引擎,下层则是存储引擎。虽然有很多不同作用的插件API,但存储引擎API还是最重要的。如果能理解MySQL在存储引擎和服务层直接处理查询时如何通过API来回交互,就能抓住MySQL的核心基础架构的精髓。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!