深入分析MySQL系列之总体架构介绍
itomcoil 2025-04-08 15:13 20 浏览
在我们详细深入介绍MySQL的方方面面之前,让我们首先来看一下MySQL的总体架构,从总体上对MySQL有所了解,这样我们在后面的具体介绍部分的时候才能够知道这些部分属于哪个模块,大概有什么样的作用。
MySQL的逻辑架构
首先我们来看一下MySQL的逻辑架构,如下图所示。
我们可以看到大概可以分成三层:
- Connection/thread handing,这一层其实和MySQL没有什么大的关系,在一般的C/S架构中都会存在,一般用来处理相关的连接,认证,安全等等方面,我们不具体介绍。
- Parser/Optimizer。这一层就是MySQL的大脑了,它主要工作就是解析查询语句,分析并进行优化,所有跨storage engines的函数都是在这里实现的,比如Stored Procedures,views等等。
- Storage Engines。顾名思义,这一层的主要作用就是存储和查询数据。MySQL支持很多种不同的Storage Engine,我们在后面一一给大家介绍。
并行控制
在了解了MySQL的逻辑架构之后,我们来看一下MySQL对一些常见数据库的问题的处理方法。第一个问题当然就是我们常见的并行控制,简单说就是有读写同时发生的时候会如何处理。我们在之前的文章介绍过常见的处理方法,这里MySQL选用的是读写锁,也就是说读获取锁的时候,可以有多个读同时进行,但是写的锁是排外的,也就是说有写获取锁,那么任何别的读和写都没有办法获取相应的锁。
使用锁有一个重要的问题就是如何确定锁的粒度,说白了,你把锁加在越大的粒度上,并行的性能就会降低,因为拿不到锁的概率就会变大。假如你把锁的粒度搞到比较小,拿不到锁的概率就会变低,这样并行的性能就会变好,但是问题是锁消耗的资源其实是很大的看,粒度越小就意味着需要更多的锁,从而有更多的资源消耗。这就是我们需要考虑的trade off。
MySQL在这个方面提供了一些选择,根据不同的Storage engine可以实现不同的锁机制和锁粒度。不过通常来说有两种锁的机制比较常见:
- 表锁:顾名思义,即使lock整个表。每次写一个表的时候都去抓这个表锁,也就意味着其它任何读写都需要等待这个锁。
- 行锁:这个锁的粒度相比表锁来说就细了很多,它是应用到一行上面的。也就是说只有这行的数据被修改的时候,才会影响到需要修改这行数据的读和写。这样一来其实并行读写的性能就会变得比较好。
大多数MySQL使用的不是简单的行锁。他们使用的是行锁和一种称之为多版本同步控制(MVCC)的技术。这个技术我们在之前的《Snapshot的隔离和Repeatable的读》中有详细的介绍。
Transaction
Transaction是一个通用的概念,这里我们不详细介绍,大家可以参考《Transactions的基本概念和介绍》这篇文章。
具体到MySQL,它有不同的storage engine支持Transaction,我们这里以最推荐的InnoDB来说明。
默认来说,单独的Insert,Update以及Delete操作是被隐式地转变成 一个Transaction并且立即commit的。也就是我们常说的AUTOCOMMIT。你可以使用SET AUTOCMMIT = 0/1来关掉或者打开这个功能。注意关掉之后,你就会一直在一个transaction里面,直到你commit或者rollback。
另外MySQL还可以自己设置隔离的级别,你可以简单使用下面这个命令来进行设置
如果你想了解具体关于transaction的隔离相关知识,可以参见这些文章:
《Transaction弱隔离之读提交的介绍和实现》
《Snapshot的隔离和Repeatable的读》
《Transaction弱隔离之更新丢失》
《Transaction弱隔离之Write Skew和Phantoms》
《Transaction Serializable隔离之串行执行》
《Transaction Serializable隔离之两阶段锁》
《一文带你深入理解Serializable隔离最新技术SSI》
相信读了这些文章之后,你会对Transaction的隔离相关内容有一个非常清晰的理解。
需要注意的是在MySQL中,transaction是在storage engine level实现的,这也就意味着假如你一个transaction设计多个不同的engine,那么这个transaction是不可靠的,因为不同的engine都有自己的设置,尤其是需要rollback的时候,可能transaction在其中一个engine中的内容被rollback了,而另外一个则没有。当然有时它会报错,但是很多时候都不会有这样的错误出现,所以你自己需要小心。
另外InnoDB使用的是两阶段锁,同时它也支持现实锁的设置,如下所示,这个是MySQL 8.0的新的功能。
Replication
MySQL中的replication使用的是pull的模式,也就是说它的每个replica是周期性的到source那边进行pull最新的log。简单的示意图如下所示:
通常来说为了更好地达到replication的目的,我们需要有最少3个replica,他们最好能分布在不同的数据中心(位置)。这样即使有灾难发生,比如地震等等,我们也能保证有至少一个repica是可以使用的。有关replication的基础知识可以参见这篇文章《分布式系统之leader-followers Replication深入介绍》。
Storage Engines
MySQL支持很多不同的Storage Engine,你可以根据自己的应用需求来进行选择。每个版本的MySQL对Storage Engine都有不同的支持。具体可能需要大家参考各个版本的说明。
在8.0之前,MySQL每个数据库是按照文件系统中的子目录格式来存储的。你创建了一个表,MySQL把表保存成一个.frm文件(定义)和一个.ibd文件(存储数据)。所以你创建了一个表Test,就会有两个文件出现,一个是Test.frm一个是Test.ibd。假如你使用了partition的话,还会有一个Test.par文件。
在8.0之中,MySQL重新定义了表的metadata,把它直接包含到标的.ibd文件中。这样一来表的结构就支持了transaction和atomic数据定义的改变。这样我们可以使用一个基于LRU的memory cache来保存partition的定义,表的定义等等。这样可以有效的降低了IO的消耗。
下面我们来看几种常见的存储引擎:
InnoDB引擎
我们其实上文也提到过,InnoDB是MySQL默认的也是最常见的存储引擎。它主要应用于那些很短的transaction。另外它的性能很好,且支持自动crash恢复,所以常见的无transaction应用也会使用它。
InnoDB使用的MVCC来实现concurrency的处理,并且实现了所有的四种隔离。默认是Repeatable read的隔离。它使用的cluster index,所以primary key的查询很快,但是secondary index则有可能受primary key影响。
InnoDB有一些内置的优化,比如预测读,内存哈希索引加速查询,插入buffer来加速插入操作等。后面我们会再写几篇文章来详细介绍这些内容。
JSON文档支持
从5.7版本开始,MySQL的InnoDB开始支持JSON格式的自动validation以及快速读。和以前的BLOB的存储方式相比有了很大的进步。紧接着InnoDB设置可以支持一些基于JSON的SQL函数。8.0.7之后,开始支持JSON数组的多指索引。这可以进一步加速JSON格式的匹配某种pattern的读速度。
MYISAM
这个引擎是MySQL的第一个引擎,也是5.6之前的默认引擎。它不支持transaction也不支持行锁。在8.0中已经完全移除了。
Archive Engine
Archive Engine只支持INSERT和SELECT查询,直到5.1才支持索引,相比来说,磁盘IO消耗会小很多。它只是一个简单的为高速插入和压缩设计的引擎。
CSV Engine
CSB引擎可以把逗号分割文件解析成表格,但是不支持索引。所以可以很方便地进行csv文件的导入和导出。
Memory Engine
这个引擎是用来匹配快速读写或者不需要在重启时保存的场景的。所有的数据都是保存在memory中,所以查询速度很快,不需要等待I/O。但是不会有数据保存。其实MySQL内部会使用它来作为一些临时表的结果保存。当然数据太大,也会把它转变成其他格式比如MyISAM表保存到磁盘中等。
Merge Storage Engine
它是多个MyISAM的组合,现在已经被废弃了。
总结
至此,本文详细介绍了MySQL的基本架构以及常见的并行控制,transaction, replication的实现。最后还介绍了各种不同的Storage Engine,希望大家阅读后能对MySQL有一个大概的了解。
总结了很多有关于java面试的资料,希望能够帮助正在学习java的小伙伴。由于资料过多不便发表文章,创作不易,望小伙伴们能够给我一些动力继续创建更好的java类学习资料文章,
请多多支持和关注小作,别忘了点赞+评论+转发。右上角私信我回复【03】即可领取免费学习资料谢谢啦!
原文出处:
https://donggeitnote.com/2021/07/07/mysql-architecture/?hmsr=toutiao.io&utm_campaign=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
相关推荐
- selenium(WEB自动化工具)
-
定义解释Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7,8,9,10,11),MozillaF...
- 开发利器丨如何使用ELK设计微服务中的日志收集方案?
-
【摘要】微服务各个组件的相关实践会涉及到工具,本文将会介绍微服务日常开发的一些利器,这些工具帮助我们构建更加健壮的微服务系统,并帮助排查解决微服务系统中的问题与性能瓶颈等。我们将重点介绍微服务架构中...
- 高并发系统设计:应对每秒数万QPS的架构策略
-
当面试官问及"如何应对每秒几万QPS(QueriesPerSecond)"时,大概率是想知道你对高并发系统设计的理解有多少。本文将深入探讨从基础设施到应用层面的解决方案。01、理解...
- 2025 年每个 JavaScript 开发者都应该了解的功能
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.Iteratorhelpers开发者...
- JavaScript Array 对象
-
Array对象Array对象用于在变量中存储多个值:varcars=["Saab","Volvo","BMW"];第一个数组元素的索引值为0,第二个索引值为1,以此类推。更多有...
- Gemini 2.5编程全球霸榜,谷歌重回AI王座,神秘模型曝光,奥特曼迎战
-
刚刚,Gemini2.5Pro编程登顶,6美元性价比碾压Claude3.7Sonnet。不仅如此,谷歌还暗藏着更强的编程模型Dragontail,这次是要彻底翻盘了。谷歌,彻底打了一场漂亮的翻...
- 动力节点最新JavaScript教程(高级篇),深入学习JavaScript
-
JavaScript是一种运行在浏览器中的解释型编程语言,它的解释器被称为JavaScript引擎,是浏览器的一部分,JavaScript广泛用于浏览器客户端编程,通常JavaScript脚本是通过嵌...
- 一文看懂Kiro,其 Spec工作流秒杀Cursor,可移植至Claude Code
-
当Cursor的“即兴编程”开始拖累项目质量,AWS新晋IDEKiro以Spec工作流打出“先规范后编码”的系统工程思维:需求-设计-任务三件套一次生成,文档与代码同步落地,复杂项目不...
- 「晚安·好梦」努力只能及格,拼命才能优秀
-
欢迎光临,浏览之前点击上面的音乐放松一下心情吧!喜欢的话给小编一个关注呀!Effortscanonlypass,anddesperatelycanbeexcellent.努力只能及格...
- JavaScript 中 some 与 every 方法的区别是什么?
-
大家好,很高兴又见面了,我是姜茶的编程笔记,我们一起学习前端相关领域技术,共同进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力在JavaScript中,Array.protot...
- 10个高效的Python爬虫框架,你用过几个?
-
小型爬虫需求,requests库+bs4库就能解决;大型爬虫数据,尤其涉及异步抓取、内容管理及后续扩展等功能时,就需要用到爬虫框架了。下面介绍了10个爬虫框架,大家可以学习使用!1.Scrapysc...
- 12个高效的Python爬虫框架,你用过几个?
-
实现爬虫技术的编程环境有很多种,Java、Python、C++等都可以用来爬虫。但很多人选择Python来写爬虫,为什么呢?因为Python确实很适合做爬虫,丰富的第三方库十分强大,简单几行代码便可实...
- pip3 install pyspider报错问题解决
-
运行如下命令报错:>>>pip3installpyspider观察上面的报错问题,需要安装pycurl。是到这个网址:http://www.lfd.uci.edu/~gohlke...
- PySpider框架的使用
-
PysiderPysider是一个国人用Python编写的、带有强大的WebUI的网络爬虫系统,它支持多种数据库、任务监控、项目管理、结果查看、URL去重等强大的功能。安装pip3inst...
- 「机器学习」神经网络的激活函数、并通过python实现激活函数
-
神经网络的激活函数、并通过python实现whatis激活函数感知机的网络结构如下:左图中,偏置b没有被画出来,如果要表示出b,可以像右图那样做。用数学式来表示感知机:上面这个数学式子可以被改写:...
- 一周热门
- 最近发表
- 标签列表
-
- ps图案在哪里 (33)
- super().__init__ (33)
- python 获取日期 (34)
- 0xa (36)
- super().__init__()详解 (33)
- python安装包在哪里找 (33)
- linux查看python版本信息 (35)
- python怎么改成中文 (35)
- php文件怎么在浏览器运行 (33)
- eval在python中的意思 (33)
- python安装opencv库 (35)
- python div (34)
- sticky css (33)
- python中random.randint()函数 (34)
- python去掉字符串中的指定字符 (33)
- python入门经典100题 (34)
- anaconda安装路径 (34)
- yield和return的区别 (33)
- 1到10的阶乘之和是多少 (35)
- python安装sklearn库 (33)
- dom和bom区别 (33)
- js 替换指定位置的字符 (33)
- python判断元素是否存在 (33)
- sorted key (33)
- shutil.copy() (33)