课程地址:后端入门 - 存储与数据库 - 掘金 (juejin.cn)
RDBMS - 关系型数据库
介绍
特点
- 事务
- 高可用/高可靠
- 高并发
发展历程
- 网状模型:多对多
- 层次模型:树形结构,一对多
- 关系模型:利用关系来描述数据特征,所有的数据都是一张二维表
SQL语言
-
诞生:关系型数据库的12条准则的数学定义以简单的关键字语法表现出来,诞生了SQL语言
-
优点:
- 语法风格接近自然语言
- 高度非过程化
- 面向集合的操作方式
- 语言简洁,易学易用(用户不需要知道细节,只需要学会调用)
关键技术
一条SQL的一生
- 步骤:从手机上发出请求 -> 路由服务器收到请求 -> SQL语句传给数据库 -> 数据库用语法解析器 (Parser) 解析SQL语句 -> 将解析后的语法树传给优化器(Optimizer) -> 优化器根据语法树生成PlanTree -> PlanTree交给执行器(Executor)做真正的执行 -> 执行时读写数据并写入日志 -> 执行器将数据返回给用户
三大引擎
- SQL引擎:Parser、Optimizer、Executor
- 储存引擎:Data File、Log File
- 事务引擎:没有显式表现(写日志就是为了事务做准备)
SQL引擎
解析器 Parser:
- 词法分析 + 语法分析 + 语义分析
优化器 Optimizer:
-
基于规则的优化器(RBO):根据优化规则对关系表达式进行转换,同时原来的表达式被裁剪。
-
RBO的优化规则是严格的,无论如何,同一条SQL只会生成一条相同的执行计划
-
步骤:
- Transformation:根据规则来转换关系表达式,生成逻辑计划
- Build Physical Plan:将逻辑计划转变成物理执行计划
-
-
基于代价的优化器(CBO):根据优化规则后产生另一条关系表达式,同时原有表达式保留,一系列转换后生成多个执行计划,最后CBO根据统计信息和代价模型计算每个计划的Cost,最后选出Cost最小的那个。
-
相比与RBO,CBO能根据数据库中的数据信息来选择最优计划
-
统计信息和代价模型会影响CBO的结果
-
步骤:
- Exploration:根据优化规则进行等价转换,生成等价关系表达式,此时原有关系表达式会被保留
- Build Physical Plan:同上
- Find Best Plan:根据统计信息计算每个执行计划的Cost,选择Cost最小的执行计划
-
执行器 Executor
-
火山模型
- 每个Operator调用Next操作,访问下层Operator,获得下层Operator返回的一行数据,经过计算后,将这行数据返回给上层
- 优点:每个算子独立抽象实现,相互之间没有耦合,逻辑结构简单
- 缺点:每计算一条数据有多次函数调用开销,导致CPU效率不高
-
-
向量化模型
-
每个Operatort每次操作计算的不再是一行数据,而是一批数 据(Batch N行数据,计算完成后向上层算子返回一个Batch。
-
优点:
- 函数调用次数降低为1/N;
- CPU cachei命中率更高
- 可以利用CPU提供的SIMD(Single Instruction Multi Data)机制。
-
-
-
编译执行模型
- 将所有的操作封装到一个函数里面,函数调用的代价也能大幅度降低。
- LLVM动态编译执行技术
-
存储引擎 - InnoDB
-
内存 In-Memory Structures
-
缓冲池 Buffer Pool:访问表是会将数据页和索引页缓存到缓冲池中,再进行读写操作,操作结束后将其缓存起来,当下次再访问这个页时直接从缓冲池中获取,从而节省了磁盘IO开销
- chunk:每个chunk以128mb向系统分配内存,分成一个个小页面,每个小页面存储数据
- instance:整个buffer pool分成许多instance
- 通过HashMap根据page_id快速找到block
- 淘汰算法LRU:在内存中将不常使用的数据淘汰以释放内存空间
-
Log Buffer(Redo Log):日志文件存入Log Buffer,再存入Redo Log
-
-
磁盘 On-Disk Structures
- 系统表 System Tablespace:存放元信息,包括表名、列名等
- 通用表空间 General Tablespaces:常规表空间是共享表空间,可以存储多个表的数据。
- Redo Log:数据库操作后的脏页会先缓存再内存中,当脏页落盘之前服务器异常关闭会使得脏页数据丢失,而Redo Log的存在使得数据库重启时能根据Redo Log执行恢复操作,从而实现更新操作的持久化
-
页面 Page
- InnoDB在buffer pool中会将内存分配为一个个16kb的小空间,这个16kb就是一个page
-
索引 B+-Tree
- 页面内:页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定记录
- 从根到叶:中间节点存储
- 为什么叶节点要用双向链表:当范围查询时,可以直接遍历链表
事务引擎
-
原子性(Atomicity):Undo Log
- Undo Log:逻辑日志,记录数据增量变化
- 当事务失败时,数据库通过Undo Log进行回滚
- Undo Log实现了多版本并发控制(MVCC),解决读写冲突和一致性读的问题
-
隔离性(Isolation):锁
- 当两个人一起读的时候,两人都上共享锁Share Lock,让其可以一起读
- 两人一起写的时候,两人都上排他锁Exclusive Lock,让其不能并发写
- MVCC:读写互不阻塞、降低死锁概率、实现一致性读
-
一致性(Durability):Redo Log
- redo log是物理日志,记录的是页面的变化,作用是保证事务持久化,若数据写入磁盘前发生故障,从其MySQL后会根据redo log重做
字节实践
红包雨
-
难点
- 流量大
- 流量突增
- 需要高稳定性
大流量 - Sharding
-
问题背景
- 单节点容易成为瓶颈
- 单机数据容量上限
-
解决方案
- 业务层数据进行水平拆分:将数据拆分到多台服务器上
- 代理层进行分片路由
-
实施效果
- 数据库写入性能线性扩展
- 数据库容量线性扩展
流量突增 - 扩容
-
问题背景
- 活动流量上涨
- 集群性能不满足要求
-
解决方案
-
扩容DB物理节点数量
先用binlog辅助第一个服务器全部复制到第二个服务器,然后删掉服务器1的50
99,删除服务器2的050 -
利用影子表进行压测
-
流量突增 - 代理连接池
-
问题背景
- 突增流量导致大量建联
- 大量简练导致负载变大,延时上升
-
解决方案
- 业务侧预热连接池
- 代理侧预热连接池
- 代理侧支持连接队列
-
实施效果
- 避免DB被突增流量打死
- 避免代理和DB被大量建联打死
稳定性&可靠性 - 3AZ高可用
-
例子
- 被攻击
- 电缆被挖断
- 地震了停电了
- 被删库跑路了
-
解决方案
- 在多个城市建独立的机房
- 不同机房之间通过日志来同步数据
-
三机房部署
- 机房级别容灾
- 机房级别流量调度
-
proxy
- 读写分离,分库分表
- 限流,流量调度
-
监控报警
- 实时监控集群运行状态
- 提前上报集群风险
稳定性&可靠性 - HA管理
-
问题背景
- db所在机器宕机
- db节点异常宕机
-
HA的作用:当一台机器不可用时,HA能快速识别并快速应对,将其
-
解决方案
- HA服务监管、切换宕机节点
- 代理支持配置热加载
- 代理自动屏蔽宕机读节点