这是我参与「第五届青训营 」伴学笔记创作活动的第29天。主要学习了关系型数据库的一些关键技术以及企业实践。
SQL语句执行的流程
一条SQL的执行流程如下所示:
用户向RDBMS发送一条SQL指令,该语句会先经过解析器(Parser)来解析SQL语法生成语法树(AST),再经过优化器(Optimizer)生成一个执行计划,讲计划交给执行器(Executor)执行,将数据写入磁盘,操作写入日志,并将结果返回给用户。
SQL引擎
Parser
分为词法分析、语法分析、语义分析;
词法分析提取关键词(关键字、表列名、常量、运算符等); 语法分析将关键词构建成语法树; 语义分析去解析语义进行合法性校验。
Optimizer
一般采用基于规则的优化策略
- 条件简化
- 表连接优先(总是小表先进行优化)
- Scan优化(唯一索引、普通索引、全表扫描) 还有基于代价的优化策略
- 处理时间
- 资源开销
Executor
- 火山模型:每个算子调用next操作访问下层算子,获得返回数据后逐层返回;每个算子独立抽象、相互之间没有耦合、逻辑结构简单,但是函数调用开销大CPU效率低。
- 向量化: 每个算子每次操作计算的是一个batch,完成后返回一个batch;降低函数调用次数,CPU cache的命中率更高。
- 编译执行:将所有操作封装到一个函数(inline)里,函数的调用代价大幅降低。采用动态编译执行技术解决用户SQL语句多样的问题。
存储引擎
MySQL的存储引擎默认为InnoDB;内存中的数据结构有:
- Buffer Pool
- Change Buffer
- Adaptive Hash Index
- Log Buffer 磁盘中的数据结构有:
- System Tablespace
- General Tablespaces
- Undo Tabelsspaces
- Temporary Tablespaces
- Redo Log 结构如下图所示:
Buffer Pool
解决CPU计算速度和磁盘IO速度不一致的问题,把内存分为多个Page,
Page
一个Page的结构如下:
其中Hander包括
- delete_mask:标识数据是否被删除
- next_record: 下一条数据的位置
- record_type: 表示当前记录的类
B+ Tree
B树的叶子节点之间构建一个双向链表。叶节点记录索引信息。
事务引擎
状态回滚
使用Undo Log,记录数据的增量变化,利用Undo Log进行事务回滚,保证事务的原子性。
锁
数据库的锁用来保证事务的隔离性,防止多个事务并发执行时由于交叉执行而导致数据的不一致。
Redo Log
事务处理结束后,对数据的修改是永久的,即使系统故障也不会丢失,修改并不直接写入到数据库文件中,而是写入到另一个称为WAL的文件中,如果事务失败,WAL中的记录会被忽略,撤销修改,如果事务成功,将在随后的某个时间被写回到数据库文件中,提交修改。