关系型数据库 | 青训营笔记

131 阅读6分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 16 天。

RDBMS(关系型数据库)是目前使用最为广泛的数据库之一,同时也是整个信息化时代的基石。这节课通过生活中常见的场景向大家介绍RDBMS的作用、发展历程及其核心技术,最后以字节为例,展示了RDBMS的企业级实践。

经典案例

RDBMS 中 事务ACID的概念:

  • 原子性(Atomicity):事务是一个不可再分割的工作单元,事务中的操作要么都发生,要么都不发生。
  • 一致性(Consistency):数据库事务不能破坏关系数据的完整性以及业务逻辑上的一致性。
  • 隔离性(Isolation):多个事务并发访问时,事务之间是隔离的,一个事务不应该影响其它事务运行效果。
  • 持久性(Durability):在事务完成以后,该事务所对数据库所做的更改便持久的保存在数据库之中,并不会被回滚。

高可靠

高并发

发展历史

DBMS数据模型

数据库发展最初过程中,诞生过3种数据模型,最终关系型模型成为了应用最为广泛的数据库模型。

  • 网状模型:用有向图表示实体和实体之间的联系的数据结构模型称为网状数据模型。
  • 层次模型:层次数据模型是用树状<层次>结构来组织数据的数据模型。
  • 关系模型:使用表格表示实体和实体之间关系的数据模型称之为关系数据模型。

SQL语言

  • 语法风格接近自然语言;
  • 高度非过程化; 
  • 面向集合的操作方式;
  • 语言简洁,易学易用。

关键技术

SQL执行过程

在SQL执行过程中,需要经历SQL引擎、存储引擎、以及事务引擎等模块。而其中SQL引擎又分为Parser、Optimizer、Executor几个部分:

SQL引擎

Paser:经过词法分析、语法分析生成语法树,然后对语法树进行合法性校验。

  • 词法分析:将一条SQL语句对应的字符串分割为一个个token,这些token可以简单分类。
  • 语法分析:把词法分析的结果转为语法树。根据tocken序列匹配不同的语法规则,比如这里匹配的是update语法规则,类似的还有insert、delete、select、create、drop等等语法规则。根据语法规则匹配SQL语句中的关键字,最终输出一个结构化的数据结构。
  • 语义分析:对语法树中的信息进行合法性校验。

Optimizer:根据Parser产生的语法树,根据规则或者代价产生执行计划树。

  • 基于规则的化简(RBO):

  • 条件化简

  • 表连接优化:总是小表先进行连接

  • Scan优化 

  • 唯一索引 

  • 普通索引 

  • 全表扫描

  • 基于代价的优化(CBO):

  • 时间

  • I/O

  • 网络

  • CPU

  • 内存

Executor:根据计划树进行执行,常见的执行方式是火山模型。

火山模型

  • 每个Operator调用Next操作,访问下层Operator,获得下层Operator返回的一行数据,经过计算之后,将这行数据返回给上层。 
  • 优点: 每个算子独立抽象实现,相互之间没有耦合,逻辑结构简单
  • 缺点: 每计算一条数据有多次函数调用开销,导致CPU效率不高。

向量化

  • 每个Operator每次操作计算的不再是一行数据,而是一批数据(Batch N行数据),计算完成后向上层算子返回一个Batch。 
  • 优点: 函数调用次数降低为1/N;CPU cache命中率更高;可以利用CPU提供的SIMD(Single Instruction Multi Data)机制。

编译执行

  • 将所有的操作封装到一个函数里面函数调用的代价也能大幅度降低。
  • LLVM动态编译执行技术,根据优化器产生的计划,动态的生成执行代码。

存储引擎

存储引擎负责了数据的底层存储、管理和访问工作。各大RDBMS存储引擎的设计都有不少的差异,这里选择MySQL的InnoDB存储引擎来向大家做一个介绍:

Buffer Pool:存储引擎位于内存中的重要结构,用于缓存数据,减少磁盘IO的开销。

  • MySQL中每个chunk的大小一般为128M,每个block对应一个page,一个chunk下面有8192个block。这样可以避免内存碎片化。
  • 分成多个instance,可以有效避免并发冲突。
  • Page id % instance num得到它属于哪个instance
  • 当buffer pool里的页面都被使用之后,再需要换存其他页面怎么办?淘汰已有的页面
  • 基于什么规则淘汰:淘汰那个最近一段时间最少被访问过的缓存页了,这种思想就是典型的 LRU 算法了。
  • 普通的LRU算法存在缺陷,考虑我们需要扫描100GB的表,而我们的buffer pool只有1GB,这样就会因为全表扫描的数据量大,需要淘汰的缓存页多,导致在淘汰的过程中,极有可能将需要频繁使用到的缓存页给淘汰了,而放进来的新数据却是使用频率很低的数据。
  • MySQL 确实没有直接使用 LRU 算法,而是在 LRU 算法上进行了优化。
  • MySQL 的优化思路就是:对数据进行冷热分离,将 LRU 链表分成两部分,一部分用来存放冷数据,也就是刚从磁盘读进来的数据,另一部分用来存放热点数据,也就是经常被访问到数据。
  • 当从磁盘读取数据页后,会先将数据页存放到 LRU 链表冷数据区的头部,如果这些缓存页在 1 秒之后被访问,那么就将缓存页移动到热数据区的头部;如果是 1 秒之内被访问,则不会移动,缓存页仍然处于冷数据区中。
  • 淘汰时,首先淘汰冷数据区。

Page:数据存储的最基本单位,一般为16KB。

  • User Records 在页面上实际是无序的,通过一个单向链表连接

B+u Tree:InnoDB中最常用的索引结构。

  • 页面内: 页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录。
  • 从根到叶中间节点存储

事务引擎

事务引擎实现了数据库的ACID能力,这里还是以MySQL的InnoDB为例来介绍数据库内部是通过哪些技术来实现ACID:

  • Atomicity:InnoDB中通过undo日志实现了数据库的原子性,通过Undo Log,数据库可以回滚到事务开始的状态;

  • Isolation:通过Undo Log实现MVCC(多版本并发控制),降低读写冲突。

  • Durability:通过Redo Log(一种WAL实现方式)来保证事务在提交后一定能持久化到磁盘中。

  • Consistency:一致性本质上是一种业务层的限制。

企业实践

字节中是国内数据规模最大的互联网公司之一,公司内部有成千上万套RDBMS系统。这一章节还是以红包雨为案例,展示了字节是如何解决大流量、流量突增、高可靠等问题的。