开发者学堂课程【云数据库 RDS MySQL 从入门到高阶:【中级】 MySQL 数据库架构介绍】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/996/detail/15072
【中级】 MySQL 数据库架构介绍
内容介绍:
一、MySQL 单例数据库架构
二、MySQL 数据库复制
三、MySQL 高可用及进阶
四、总结
一、MySQL 单例数据库架构
1. MySQL 体系结构
从开发的角度看, MySQL 体系结构 可以分为下面几个部分:
(1)网络连接层:提供与 MySQL 服务器建立连接的支持(如写程序时,需要使用 JTPC 和数据库建联,这个操作就是通过这个模块去实现)
(2)核心服务层:主要包括系统管理和控制工具、连接池、 SQL 接口、解析器、查询优化器和缓冲六个部分
(3)存储引擎:负责 MySQL 中数据的存储与提取,与底层系统文件进行交互
(4)文件系统:负责将数据库的数据和日志存储在文件系统之上,并完成与存储引擎的交互,是文件的物理存储层
下图涵盖了 MySQL 的几个大功能模块:
2. SQL 运行过程
一条 SQL 的运行过程:
首先用户先到连接池,连接池的整体作用是可以提升性能(如 TCB协议中,三次握手和四次挥手会花费很多资源,浪费性能,而通过连接池可以提升性能),连接池分配性能之后,再通过 MySQL 查询对应数据,此时,如果缓存中已经有之前查询的数据,就会直接把缓存中的数据返回给用户;如果没有,解析层将进行 SQL 查询。然后进行 SQL 解析,再到 Parser 层进行校验生成新的解析数,然后在到优化器调优(优化器的作用是找到最优路径,采集用户的数据,生成一个执行计划)再通过查询存储引擎得到对应数据。
(1)一条查询 SQL 在 MySQL 服务中各模块的执行流程,通过各个模块功能的协同完成通过 SQL 拿到最终的磁盘数据。
(2)建立连接->从缓存获取-> Parser 层 SQL 解析并校验生成解析树->优化器调优->存储引擎获取数据
详情可见下图:
3. InnoDB 内存和存储结构
最常见的存储引擎是 InnoDB ,优势是擅长处理事务,具有自动崩溃恢复的特性。
(1)内存结构:内存结构主要包括 Buffer Pool、 change Buffer、 Adaptive Hash Index 和 Log Buffer 四大组件。其中,Buffer Pool 可以提升整体性能,如果用户查询数据发现内存已经存在数据,那么这个数据可以直接被使用,如果没有,才需要通过 IO 操作把数据放回 Buffer Pool 后再提交给用户,即通过 Buffer Pool 可以解决反复的 IO 情况。 change Buffer 是一个写缓能区,它的作用是提升写的性能。 Adaptive Hash Index 的作用是对查询功能做出优化,提升查询的性能。 Log Buffer 的作用是提升写日志的性能。
①内存 Page :Free Page、Clean Page、Dirty Page
②链表管理:Free List、Flush List、LRU List
解析:Operationing System Cache 是一个操作系统,通过 O_DIRECT 的方式,把数据输入到 Disk 中,内存管理实际上就是 Buffer Pool 的管理, Buffer Pool 储存的都是页码,页主要有三种类型:空闲页即Free Page , Clean Page (数据没有被更改的页) 和 Dirty Page(数据被更改但是没有刷入到磁盘,如果刷入到磁盘, Dirty Page 需要被回收)。而 Buffer Pool 的管理是通过链表来管理的,上述三种类型的页也是通过链表来管理,其中 Flush List 管理 Dirty Page, LRU List 提供查询缓冲(提供 LRU 机制,把数据缓存到 Buffer Pool 里面,达到活跃的页,以此来实现性能的提升。)
详情可见下图:
(2)存储结构: InnoDB 磁盘主要包含Tablespaces , InnoDВ Data Dictionary , Doublewrite Buffer、Redo Log 和 Undo Logs。其中 Doublewrite Buffer 的作用是通过 Doublewrite 的机制,在基于 Redo Log 的基础上来保证页的数据能防止局部写的情况, Redo Log 的作用是用于解决数据库事务提交还未刷入磁盘,服务器 down 机导致的数据丢失的问题(通过 Redo Log 对事务进行重做,这样可以保证提交的事物不会丢失), Undo Logs 的作用是实现 MVCC 和事务回滚。
4. Redo&Undo&MVCC
(1)Redo:用于解决数据库事务提交还未刷入磁盘,服务器down机导致的数据丢失的问题。
MySQL 如何写 Redo Log 和 Undo Logs:从业务开发的角度说,不使用 MySQL ,写一条数据的正常做法是,在内存先进行数据的修改然后刷到磁盘中。而如果使用 MySQL ,一共需要五步,第一步是,数据先在 Buffer Pool 里面进行更改,再把数据输入到 Disk 也就是磁盘中。第二步是,如果 Buffer Pool 里面没有数据,需要把磁盘中的数据 Redo Log 到 Buffer Pool 里面,第三步是,当 Buffer Pool 里有数据后,若写的数据出现异常,需要将数据进行回滚,就可以使用 Undo Logs 。第四步是,通过 Redo Log 来解决局部写的情况。第四步完成后,第五步中,Binlog 可以保证事务是完整的即保证事务已经提交,这里分为两步,首先把事务连写到 Binlog ,当Binlog 写完后,相当于事务已经被提交,此时对于 Redo Log ,这个数据就是已经写完即 Redo Log 写完,然后数据才能视作完全提交。
(2)Undo:实现 MVCC 和事物回滚
解析:上图在执行一条事务,其中包含三个事务,Undo Logs 的原始数据是14,需要改变的就是把14改成15,可以看到,数据每次在 Buffer Pool 里面更改后,会有一个指向 Undo Logs 的指针,通过这种机制可以实现事务的回滚,并且通过事物的地址可以做版本的管理即实现 MVCC
(3)MVCC :数据多版本来做到读写分离,从而实现不加锁读进而做到读写并行。利用到了数据库隐式字段和 Undo Logs 、ReadView (基于Undo Logs 来实现)。
5. TableSpace
(1)Segment:数据段、索引段、回滚段
(2)Extent:一个段包含多个区、一个区包含64个页
(3)Page:一个页包含多条记录
(4)Row:用户写入的实际数据
下图是 TableSpace 的逻辑存储结构:
解析:最上面的 Leaf node 段也就是叶子节点,里面存放了数据段、索引段和回滚段,每个段包含多个区,一个区包含64个页,并且一个页包含多条数据,数据都保存在页里面,页是 MySQL 的最小存储单位。
6. Page
简单描述页在物理的存储结构:
页主要包括六个部分:
(1)File Header (文件头) :主要包含 FIL _ PAGE _ PREV 、 FIL _ PAGE _ NEXT 。作用是管理页
一页指针和下一页指针,说是指针(页在磁盘上的偏移量)
(2)Page Header :标明记录位置和 UserRecords 统计
(3)Infimum&BuSupremum Records :描述是最小记录和最大纪录的开区间。作用是对用户写入的数据作统计
(4)Free Space :User Reckords 和 Free 、不够申请新的页。作用是让用户把数据真正存储在申请栏
(5)Page Directory :每写入一定数量 Records 作为一个 Slot ,在定位到 Page 后根据 slot 提升查找性能。主要作用就是提升性能,类似于正常使用二分法查询数据,将之前的数据记录进行分组,快速的查找到需要的数据,这样就可以提升查询性能。
(6)File Trailer (8字节 ) :低4位 Checksum 、高4位和 File Header 的 LSN 一致。作用是校验,可以保证文件的页不出错。
详情可见下图:
7. InnoDB 线程模型
(1)IO Thread :大量 AIO 读写处理,提高数据库性能(其中AIO线程主要包括四个线程 :Read Thread 、 Write Thread 、 Log Thread 、 Insert Buffer Thread )
(2)Purge Thread :事务提交后,其使用的 Undo 日志将不再需要,因此需要 Purge Thread 。主要作用是针对 Undo 日志的回收,当一个事务提交后,不再需要Undo ,而Undo 会占用巨大空间,于是可以通过 Purge Thread 定期处理 Undo ,以保证磁盘的空间不会被 Undo 占用
(3)Page Cleaner Thread : 将脏数据刷新到磁盘,脏数据刷盘后相应的 Redo Log 也就可以覆盖,即可以同步数据又能达到 Redo Log 循环使用的目的,会调用 Write Thread 线程处理。
(4)Master Thread :负责调度其他各线程,优先级最高。作用是将缓冲池中的数据异步刷新到磁盘,保证数据的一致性。包含:脏页的刷新、 Undo 页回收、 Redo 日志刷新、合并写缓冲等
详情可见下图:
8.备份机制
(1)传统备份:
MySQLDump 逻辑全备+逻辑 Binlog 日志
其中,MySQLDump 的作用是将数据 Dump 出来,让其变成可执行的 SQL ,然后再导入到 MySQL 里,这样可以保证数据一定能被写入。两者结合可以做到数据的一致性恢复,搭建备份做数据同步,同时可以将 MySQLDump 升级。
XtraBackup 物理全备( Copy 文件+Redo 增量)+逻辑 Binlog 日志
其中,XtraBackup 作用的原理是借助 copy 地址的线程,不断的把数据库里的文件拷贝出来,由于在拷贝文件的时候文件会不停的被更改,所以还需结合 Redo 增量日志进行数据的重做,保证文件数据的一致性。它的缺点是不能备份数据过大的文件,如果用户的数据大量的写入, Redo 增量 来不及运作,这个备份就会失败。
(2)快照备份:
基于 ECS 云盘快照+逻辑 Binlog 日志
相对于传统备份,快照备份更加快速,而且通过云盘备份可以解决传统备份无法备份大量数据的问题。
详情可见下图:
解析:当文件拷贝完成后,会将完成的信号发送给主线程,然后会锁住数据库,找到一致性点的位置,当所有的数据都达到了一个共同的时刻之后,再把其他的文件一起拷贝出来,此时 Redo 停止工作,架起的这把锁被释放,同时备份完成。
二、MySQL 数据库复制
1. MySQL 数据复制原理
(1)Binlog :主备复制基于 Binlog 日志( AliSQL Redo )
(2)Dump Thread (主):为每个 Slave 的I/O Thread 启动一个 Dump 线程,用于向其发送 Binary Log Events
(3)I/O Thread :向 Master 请求二进制日志事件,并保存于中继日志中
(4)SQL Thread :从中继日志中读取日志事件,在本地完成重放
如下图所示:
解析:主备复制是基于 Binlog 的,主节点上会启用一个 Dump Thread , Dump Thread 的主要作用是把日志发送给 Slave ,Slave 节点有一个 I/O 线程 ,I/O 线程会把接受的日志保存在 Redo Log 里,然后 SQL Thread 再进行 Redo Log 的存放,这样就实现了一个数据的复制。
2. MySQL 复制架构
(1)主从架构
解析:主节点将数据同步到多个从节点,上图中显示的一主多从的架构,当然也可以利用 MySQL 的多源复制的特性实现多主一从架构
(2)级联架构
解析:相当于一个 Slave 节点下面还有多个 Slave 节点,主节点将数据同步到一个从节点,其他的从节点在向从节点复制数据
3. MySQL 复制模式
(1)异步&半同步
MySQL 复制通常情况采用异步模式,没有从库的 ACK 应答,半同步复制的机制是只有当主节点和从节点同步完成,仅有一台同步完成即可,返回写入完成,这样的机制保证了数据的安全性。
解析:异步模式和半同步复制的区别是,前者没有从库的 ACK 应答而后者有。对于后者,当一个事务开启时,是需要发送给 Slave 的,然后I/O Thread 转成 Redo Log 之后,会发一个 ACK 应答,表示已经同步,此时事务才会被提交。而对于前者,它没有 ACK 应答,是不需要 Slave 的,这样就会导致 Slave 的延迟。半同步复制的优点是可以让数据的同步更加友好,但是它也存在丢数据的情况。
(2)加密传输
解析:在默认的主从复制过程或远程连接到 MySQL/MariaDB 所有的链接通信中的数据都是明文的,外网里访问数据或则复制,存在安全隐患。通过 SSL/TLS 加密的方式进行复制的方法,来进一步提高数据的安全性。
三、MySQL 高可用及进阶
1. MySQL 高可用原理
(1)服务冗余
把服务部署多份,当某个节点不可用时,切换到其他节点,服务冗余对于无状态的服务是相对容易的
(2)故障转移
服务冗余之后,当某个节点不可用用时,要做到快速切换
具体流程可见下图:
解析:首先需要对主从集群中 Master 进行监控,确保 Master 是可以使用的,如果 Master 被 down 不可以使用,就需要 VIP 实现 Master 故障切换,对异常节点进行修复,切换之后,就可以重新搭建新 Slave 并进行同步。
2. Keepalived 架构
(1)背景:业界传统高可用方案
(2)Core : keepalived 的核心,负责主进程的启动和维护,全局配置文件的加载解析等
(3)Check:负责 HealthChecker ,包括了各种健康检查方式以及对应的配置的解析包括 VS 的配置解析可基于脚本检查对 PVS 后端服务器健康状况进行检查
(4)VRRP: VRRP 进行通信,通过竞选机制确定主备,主优先级高于备,主会一直发送 VRRP 广播包,告诉备它还活着,此时备不会抢占主,当主不可用时(即备监听不到主发送的广播包),备会启动相关服务接管资源,保证业务连续性。但无法进行第三方仲裁、会出现脑裂情况
详情可见下图:
解析:上图是一个主从架构的图,可以看到 keepalived 主要使用虚拟路由的协议,主会一直发送广播包,告诉备它还活着,当 Slave 收不到广播包之后,就会认为主已经失去能力了,于是备会启动相关服务接管资源,此时用户的业务移交给 Slave 处理,通过脚本的方式把 Slave 提升为主,这样就相当于完成了一次切换。
Keepalived 架构的缺点是没有第三方的仲裁,在极端的网络情况下,会出现脑裂的情况以及主备同时写入数据的情况,这会导致数据不一致。解决这个问题可以通过第三方机制的方式去控制 keepalived 架构。
3. MHA 架构
(1)MHA 背景:业界方案
(2)MHA 组成:包括 Manager 节点和 Node 节点,管理节点一般独占机器,Node节点一般和每台 MySQL Server 在一起
(3)MHA 工作原理:Node 节点通过解析各 MySQL 志来进行一些操作, Manager 节点将和每个 Node 节点通信,判断其 Node 上的 MySQL 是否正常。若发现故障,则直接把他的 Slave 提升为 Master ,其他 Slave 都挂到新 Master 上,此过程过程对用户透明
如图:
解析:上图是 MHA 的管理节点,管理节点可以管理多个集群,可以看到,第一个集群中的每个节点上都有一个 MHA Node ,它的作用是判断每个节点是否是正常的,Manager 节点和每个 Node 节点都会进行通信,若发现故障,则直接把 Slave (Slave1 或者 Slave2) 提升为 Master , Master 降为 Slave ,然后其他 Slave 都挂到新 Master 上,整个过程对用户透明,这样就完成了一次切换,保证了服务的可用性。
4. MGR 架构
MGR 架构与 Keepalived 架构以及 MHA 架构不同,后两者主要是基于 MySQL 上层去运作,而 MGR 架构 是内核去做选举的一个过程,相当于内核已经把功能实现了,所以 MGR 架构是基于 Paxos 协议,通过多数派的机制来达到内核选举的目的,这样就无需上层服务层先去实现功能,而且MGR 还提供了多主和单主的模式
(1)特性:核心解决异步复制和半同步复制数据致性问题,可保证实物不丢失
(2)多数派:基于 Paxos 协议,若干节点组成复制组,一个事务发起提交,必须经过半数节点以上的决议通过,才可正常提交
(3)集群模式:
①多主:客户端可随机向 MySQL 节点写入数据
②单主:集群选出新主节点提供写,源主和其他节点提供读
详情可见下图:
四、总结
1.内容
以上内容偏向于当前互联网几种常用方式,未涵盖各大厂自研的内容
2. MySQL 内核延伸:
业界基于 MySQL 内核也有多种版本,比如 AliSQL/OcceanBase/Percona/Tidb 等。