MySQL 深入浅出系列01—MySQL 架构

本文详细介绍了MySQL的逻辑架构,包括服务器与存储引擎的交互,连接管理和安全性,以及并发控制中的读写锁和锁粒度。重点分析了InnoDB和MyISAM两种主要存储引擎的特点和性能优化。
摘要由CSDN通过智能技术生成

1 MySQL 逻辑架构

MySQL 服务器逻辑架构图。
在这里插入图片描述

服务器通过 AP1 与存储引擎进行通信 。接口屏蔽了不同存储引擎之间的差异,使得这些差异对上层的查询过程透明。存储引擎 API 包含几十个底层函数,用于执行诸如“开始一个事务” 或者“根据主键提取一行记录” 等操作。但存储引擎不会去解析 SQL(例外:InnoDB 会解析外键定义),不同存储引擎之间也不会相互通信,而只是简单地响应上层服务器的请求

连接管理与安全性
每个客户端连接都会在服务器进程中拥有一个线程,这个连接的查询会在这个单独的线程中执行,该线程只能轮流在某个 CPU 核心或者 CPU 中运行。服务器会负责缓存线程,因此不需要为每一个新建的连接创建或者销毁线程。

MySQL 5.5 或者更新的版本提供了一个 API,支持线程池 (Thread-Pooling) 插件,可以使用池中少量的线程来服务大量的连接。

客户端连接到服务器,服务器会对其进行基于用户名、原始主机信息和密码的认证;若使用了安全套接字 (SSL),还可使用 X.509 证书认证。一旦客户端连接成功,服务器会继续验证该客户端是否具有执行某个特定查询的权限,是否可执行相关操作。

优化与执行
MySQL 会解析查询,并创建内部数据结构 (解析树),然后对其进行各种优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。用户可以通过特殊的关键字提示 hint) 优化器,影响它的决策过程。也可以请求优化器解释 (explain) 优化过程的各个因素,使用户可以知道服务器是如何进行优化决策的,并提供一个参考基准,便于用户重构查询和 schema、修改相关配置,使应用尽可能高效运行。

优化器并不关心表使用的是什么存储引擎,但存储引紫对于优化查询是有影响的。优化器会请求存储引擎提供容量或某个具体操作的开销信息,以及表数据的统计信息等。例如,某些存储引擎的某种索引,可能对一些特定的查询有优化。

对于 SELECT 语句,在解析查询之前,服务器会先检查查询缓存 (Query Cache),如果能够在其中找到对应的查询,服务器就不必再执行查询解析、优化和执行的整个过程,而是直接返回查询缓存中的结果集。

2 并发控制

只要有多个查询需要在同一时刻修改数据,都会产生并发控制的问题。过论 MySQL 在两个层面的并发控制:服务器层与存储引擎层。只简要地讨论 MySQL 如何控制并发读写。

读写锁

并发控制。实现一个由两种类型的锁组成的锁系统。两种类型的锁通常被称为共享锁 (sharedlock) 和排他锁 (exclusivelock),也叫读锁 (read lock) 和写锁 (write dock)。锁的概念如下:读锁共享,或说是相互不阻塞的。多个客户在同一时刻可以同时互不干扰地读取同一个资源。写锁排他, 也就是说一个写锁会阻塞其他的写锁和读锁,出于安全策略考虑,只有这样才能确保在给定的时间里,只有一个用户能执行写人,井防止其他用户读取正在写入的同一资源。

锁粒度

一种提高共享资源并发性的方式就是让锁定对象更有选择性。尽量只锁定需要修改的部分数据,而不是所有的资源。更理想的方式是,只对会修改的数据片进行精确的锁定。 锁定的数据量越少,则系统的并发程度越高,只要相互不发生冲突即可。加锁需要消耗资源。各种锁的操作:获取锁、检查锁是否解除和释放锁等。花费大量时间管理锁,而不是存取数据,必然影响系统性能。每种 MySQL 存储引擎都可以实现自己的锁策略和锁粒度。

表锁 (table lock):最基本、开销最小的锁策略。锁定整张表,一个用户写操作先获取写锁,会阻塞其他用户的读写操作。读锁之间相互不阻塞。特定场景表锁也可能有良好的性能,如 READ LOCAL 表锁支持某些类型的并发写操作。写锁也比读锁有更高的优先级,因此一个写锁请求可能会被插人到读锁队列的前面 (反之读锁则不能插人到写锁的前面)。尽管存储引擎可以管理自己的锁,MySQL 本身还是会使用各种有效的表锁来实现不同的目的,如服务器会为诸如 ALTER TABLE 之类的语句使用表锁,而忽略存储引擎的锁机制。

行级锁 (rowlock):最大程度地支持并发处理 、最大的锁开销。InnoDB 、XtraDB以及其他一些存储引擎中实现 了行级锁。行级锁只在存储引擎层实现,而 MySQL 服务器层没有实现。服务器层完全不了解存储引擎中的锁实现。

3 MySQL 的存储引擎

在文件系统中,MySQL 将每个数据库 (也可以称之为 schemna)保存为数据目录下的一个子目录。创建表时,MySQL 会在数据库子目录下创建 一个和表同名的 .frm 文件保存表的定义。因为 MySQL 使用文件系统的目录和文件来保存数据库和表的定义,大小写敏感性和具体的平台密切相关。在 Windows 中,大小写是不敏感的 ,而在类 Unix 中则是敏感的。不同的存储引擎保存数据和索引的方式是不同的,但表的定义则是在 MySQL 服务层统一处理的。在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

InnoDB 存储引擎

InnoDB 是 MySQL 的默认事务型引擎,也是最重要、使用最广泛的存储引擎。它被设计用来处理大量的短期 (short-lived) 事务,短期事务大部分情况是正常提交的,很少会被回滚。InnoDB 的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中也很流行。除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑 InnoDB 引擎。

InnoDB 的数据存储在表空间(tablespace)中,表空间是由 InnoDB 管理的一个黑盒子,由一系列的数据文件组成。InnoDB 采用 MVCC 来支持高井发,并且实现了四个标准的隔离级别。其默认级别是 REPEATABLE READ(可重复读),并且通过间隙锁(nextkeylocking) 策略防止幻读的出现。 间隙锁使得 InnoDB 不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插人。

InnoDB 表是基于聚簇索引建立的。InnoDB 的索引结构和 MySQL 的其他存储引擎有很大的不同,聚簇索引对主键查询有很高的性能 。不过它的二级索引中必须包含主键列,所以如果主键很大,其他的所有索引都会很大。因此,若表上的索引较多的话,主键应当尽可能的小InnoDB 的存储格式是平台独立的,就是说可以将数据和索引文件从 Intel 平台复制到 PowerPC 或者 Sun SPARC 平台。
InnoDB 内部优化:从磁盘读取数据时采用的可预测性预读、自动在内存创建 hash 索引以加速读操作的自适应哈希索引 (adaptive hash index)、能加速插入操作的插入缓冲区 (insert buffer)等。

MyISAM 存储引擎

在 MySQL 5.1 及之前的版本,MyISAM 是默认的存储引擎。MyISAM 提供了大量的特 性,包括全文素引、压缩、空间函数 (GIS) 等,但 MyISAM 不支持事务和行级锁,缺陷是崩溃后无法安全恢复。适合只读数据,或表比较小,可以忍受修复(repair) 操作。

存储:MyISAM 会存储在两个文件中:数据文件 .MYD 和索引文件 .MYI。MyISAM 表可以包含动态或者静态(长度固定)行,根据表定义决定行格式。MyISAM 表可以存储的行记录,受限于磁盘空间,或操作系统的单个文件的最大尺寸。

MyISAM 特性
加锁与并发:表锁,读加共享锁,写加排他锁。但有读取查询时,也可以往表插入新的记录(并发插入,CONCURRENT INSERT)。
修复:CHECK TABLE mytable 检查表的错误。有错误用 REPAIR TABLE mytable 进行修复。如果 MySQL 服务器已经关闭,可以通过 myisamchk 命令行工具进行检查和修复操作。
索引特性:即使是 BLOB 和 TEXT 等长字段,也可以基于其前500个字符创建索引。支持全文索引-基于分词创建的索引,可以支持复杂查询。
延迟更新索引键 (Delayed Key Write):创建 MyISAM 表的时候,如果指定了 DELAY_KEY_WRITE 选项,每次修改执行完成后,不会立刻将修改的索引数据写入磁盘,而是会写到内存中的键缓冲区 (in-memory key buffer),只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写入到磁盘。这种方式可以极大地提升写人性能,但是在数据库或者主机崩溃时会造成索引损坏,需要执行修复操作。延迟更新索引键的特性,可以在全局设置,也可以为单个表设置。

MyISAM 压缩表:如果表在创建并导入数据以后,不会再进行修改操作,或许适合采用 MyISAM 压缩表。使用 myisam pack 对 MyISAM 表进行压缩(也叫打包 pack)。压缩表是不能进行修改的(除非先解压,修改,再压缩)。好处:极大减少磁盘空间占用,因此也可以减少磁盘 I/O ,从而提升查询性能。压缩表也支持索引,但索引也是只读的。读取压缩表数据时的解压带来的开销影响并不大,而减少 I/O 带来的好处则要大得多。压缩时表中的记录是独立压缩的,所以读取单行的时候不需要去解压整个表 (甚至也不解压行所在的整个页面)。

MyISAM 性能:MyISAM 引擎设计简单,数据以紧密格式存储,某些场景下的性能很好。 MyISAM 有一些服务器级别的性能扩展限制,比如对索引键缓冲区 (key cache )的 Mutex 锁,MariaDB 基于段 (segment) 的索引键缓冲区机制来避免该问题。但 MyISAM 最典型的性能问题还是表锁的问题,如果你发现所有的查询都⻓期处于“Locked” 状态, 那么毫无疑问表锁就是罪魁祸首。

4 MySQL 内建的其他存储引擎

Archive 引擎只支持 INSERT 和 SELECT 操作,在 MySQL 5.1 之前也不支持索引。会缓存所有写并利用 zlib 对插入行压缩,比 MyISAM 磁盘 I/O 更少。但 SELECT 查询每次执行全表扫描,更适合日志和数据采集类应用,或许需要快速 INSERT 操作的场合。支持行级锁和专用缓冲区,实现高并发插入。在一个查询开始直到返回表中存在的所有行数之前,Archive 引肇会阻止其他的 SELECT 执行,以实现一致性读。另外实现了批量插人在完成之前对读操作是不可见的。模仿 MVCC一些特性,但是非事务型引擎,而是一个针对高速插入和压缩做了优化的简单引擎。

Blackhole 引擎:没有实现任何的存储机制,它会丢弃所有插人的数据。但是服务器会记录 Blackhole 表的日志,所以可以用于复制数据到备库,或者只是简单地记录到日志。这种特殊的存储引擎可以在一些特殊的复制架构和日志审核时发挥作用。 但会碰到过很多问题,不推荐。

CSV 引擎:将普通的 CSV文件 (逗号分割值的文件)作为 MySQL 的表来处理,不支持索引。CSV 引擎可以在数据库运行时拷人或者捞出文件。可以将 Excel 等电子表格软件中的数据存储为 CSV 文件,然后复制到 MySQL 数据目录下,就能在 MySQL 中打开使用。同样, 如果将数据写入到一个 CSV 引擎表 , 其他的外部程序也能立即从表的数据文件中读取 CSV 格式的数据。因此 CSV 引擎可以作为一种数据交换的机制

Federated 引擎访问其他 MySQL 服务器的一个代理,会创建一个到远程 MySQL 服务器的客户端连接,并将查询传输到远程服务器执行,然后提取或者发送需要的数据。 最初设计该存储引擎是为了和企业级数据库如 Microsoft SQLServer 和 Oracle 的类似特性竞争的,更多的是一种市场行为。看起来提供了一种很好的跨服务器的灵活性,但也经常带来问题,默认是禁用的。Maria DB 使用了它的一个后续改进版本,叫做 FederatedX。

Memory 引擎:如需要快速访问数据,并且数据不会被修改,重启以后丢失也没有关系,那么使用 Memory 表(以前也叫做 HEAP 表)是非常有用的。Memory 表至少比 MyISAM 表要快一个数量级,因为所有的数据都保存在内存中,不需要进行磁盘 I/O。Memory 表的结构在重启以后还会保留,但数据会丢失。
Memroy 表在很多场景可以发挥好的作用:
用于查找 (lookup) 或者映射 (mapping),例如将邮编和州名映射的表。
用于缓存周期性聚合数据 (periodically aggregated data) 的结果。
用于保存数据分析中产生的中间数据
Memory 表支持 Hash 索引,查找操作非常快。虽然速度非常快,但还是无法取代传统的基于磁盘的表。Memroy 表是表级锁,因此并发写入的性能较低,不支持 BLOB 或 TEXT 类型的列,并且每行的长度是固定的,所以即使指定了 VARCHAR 列,实际存储也会转换成 CHAR 列,导致部分内存的浪费 (其中一些限制在Percona 版本已经解决)。如果 MySQL 在执行查询的过程中需要使用临时表来保存中间结果,内部使用的临时表就是 Memory 表 。如果中间结果太大超出 Memory 表的限制,则临时表会转换成 MyISAM 表。

不要混淆Memory表和临时表。临时表是指使用 CREATE TEMPORARY TABLE语句创建的表,它可以使用任何存储引擎,因此和 Memory 表不是一回事。临时表只在 25 单个连接中可见,当连接断开时,临时表也将不复存在。

Merge 引擎:是 MyISAM 引擎的 一个变种,由多个 MyISAM 表合并而来的虚拟表。如果将 MySQL 用于日志或者数据仓库类应用,该引擎可以发挥作用。但引入 分区功能后,该引擎已经被放弃 。

NDB 集群引擎:2003年,当时的 MySQL AB 公司从索尼爱立信公司收购了NDB 数据库,然后开发了 NDB 集群存储引擎,作为 SQL 和 NDB 原生协议之间的接口。MySQL 服务器、NDB 集群存储引擎,以及分布式的、share-nothing的、容灾的、高可用的 NDB 数据库的组合, 被称为 MySQL 集群 (MySQLCluster)。

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值