MySQL架构


在读了《MySQL45讲》后,挺有感触的,想着结合自己的实践写一下自己的理解。

MySQL架构

存储层

首先自下而上的谈吧,在MySQL 的源代码中,在3.23.34a版本之前,它还没有InnoDB,而那时默认的还是 MyISAM引擎。在InnoDB横空出世之后,由于它支持事务、支持行级锁定等特性,备受青睐,在后来被收购后,并入了MySQL中,从MySQL 5.5.5 版本开始,它成为了默认存储引擎。

存储引擎层的职责是数据的存储和提取,其架构模式是插件式的,截至到目前,它支持 InnoDB、MyISAM、Memory 等多个存储引擎。但即使你的表有着不同的存储引擎,server层确是共用的。

在这里插入图片描述

连接器

客户端的每个连接我们都可以通过show processlist命令进行查看,如图Host表示连接的主机,Command表示连接状态,Sleep时为空闲连接,Query则为“工作”的状态了,而且工作做的原因,是我现在执行了这个命令show processlist
在这里插入图片描述
注意,客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时,这个参数可以在配置文件种修改或者命令行方式修改。

在这里插入图片描述

在数据库中,连接分为短连接(执行较少次数的查询后就断开,下次重新新建)和长连接,在连接断开之后,需要重连,在实际业务中,一般会借助数据库连接池进行操作,而有时会出现程序连接数据库时莫名其妙的报错,此时可以检查是否是这个参数在“捣鬼”。

另一方面,建立连接的过程是耗时的操作,可以通过抓包进行分析,MySQL的连接建立在TCP传输协议的基础之上,在连接和断开时经历的是3次握手和4次分手,还需要经过权限验证等操作,所以尽量减少建立连接的动作,这也是我们需要数据库连接池的原因。


查询缓存

关于查询缓存,,它不太适合时代的发展了,在MySQL8.0之后就没有这个功能了。因为它每次只要有对一个表有所更新,这个表上所有的查询缓存都会被清除,而这对业务(特别是那些更新特别频繁的表)是不能忍受的。但是我想啊,为什么给这个表生成一个id,然后每次更新缓存只删除涉及到更新操作的表呢?或许是因为维护起来比较麻烦,还要消耗内存?也可能是市场上出现了很多优秀的缓存产品了觉得没必要费力完善,而且比起缓存和数据存储集成在一起,相互分开更能增加系统的健壮性?


分析器

顾名思义,一条SQL语句过来时,需要对 SQL 语句做解析才能明白你想干嘛。而在这里,分析器负责词法分析和语法分析,即将查询分解成一个Identifier(词法分析),构造一棵解析树,确保没有语法错误(语法分析)。

select id from student;

在上面的SQL语句中,从select开始作分析,然后还需要把id是识别为列名,把from后面的student识别为表名,接着,还要做“语法分析”,从而判断你的语句是否满足SQL语法。在这个阶段,我们经常容易遇到的bug是:

You have an error in your SQL syntax; check the manual that 
corresponds to your MySQL server version for the right syntax 
to use near ‘XXX’

补充一点,表的字段是事先定义好的,所以可以直接读取的,不需要打开表,所以在这个阶段我们可以不需要打开表就能读取相应的字段名


优化器

优化器这个就比较厉害了,在设计索引、联表查询时可以发挥关键的作用,从而较少操作时间,例如:多个索引的时候,决定使用哪个索引可以达到“快速”(防止回表)的目的,或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序,当然了如果你使用了left join或者right join那就不行了,而使用join,数据库可以帮你选择数据量较少的表在前面。


执行器

在执行器阶段,还需要先判断一下你对这个表 有没有执行查询的权限,如果没有,就会返回没有权限的错误。为什么没有在连接时做判断?因为连接时,只是判断你有没有操作这个数据库的权限,而你是否可以读取这个表,是需要经过语义分析后才能知道的。

然后才是打开表继续执行,打开表的时候,会根据表的引擎定义,去使用这个引擎提供的接口。


数据库连接池

在讲数据库连接器时,分析了连接时的麻烦的原因,所以数据库连接池是一种必要的存在。所以,这里也趁机总结一下业上常用的数据库连接池的类型。

  • 1.dbcp
    dbcp是Tomcat使用的连接池组件,这个连接池可以设置最大和最小连接,连接等待时间等。优缺点:稳定性还是可以,不过速度稍慢,在大并发量的压力下稳定性有所下降,此外不提供连接池监控。
initialSize :连接池启动时创建的初始化连接数量(默认值为0)

maxActive :连接池中可同时连接的最大的连接数(默认值为8,根据应用场景定)

maxIdle:连接池中最大的空闲的连接数,超过的空闲连接将被释放,如果设置为负数表
示不限制(默认为8个,maxIdle不能设置太小,因为假如在高负载的情况下,连接的打
开时间比关闭的时间快,会引起连接池中idle的个数上升超过maxIdle,而造成频繁的连
接销毁和创建,类似于jvm参数中的Xmx设置)

minIdle:连接池中最小的空闲的连接数,低于这个数量会被创建新的连接(默认为
0,该参数越接近maxIdle,性能越好,因为连接的创建和销毁,都是需要消耗资源的,
但是不能太大,因为在机器很空闲的时候,也会创建低于minidle个数的连接,类似于
jvm参数中的Xmn设置)

maxWait:最大等待时间,当没有可用连接时,连接池等待连接释放的最大时间,超
过该时间限制会抛出异常,如果设置-1表示无限等待(默认为无限,调整为60000ms,
避免因线程池不够用,而导致请求被无限制挂起)
  • 2.c3p0
    c3p0是另外一个开源的连接池,功能呢,和上一个差不多。优缺点:在大并发量的压力下稳定性也有一定保证,此外不提供连接池监控。

  • 3.proxool
    proxool基本功能大差不差,优缺点:稳定性有一定问题,有一个需要长时间跑批的任务场景任务,优势–连接池监控。

  • 4.Druid
    Druid是Java语言中最好的数据库连接池(?),主要解决的是对于大量的基于时序的数据进行聚合查询,Druid能够提供强大的监控和扩展功能。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

legendaryhaha

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值