“这是我参与「第五届青训营 」伴学笔记创作活动的第 17 天”
3 MYSQL关键技术
3.1 一条SQL的一生
1、SQL引擎:Parse+Optimizer+Exceutor;
- 1)Parse引擎:查询解析
- SQL接近自然语言,首先将文本解析成结构化语言(AST)抽象语法树;
- 2)Optimizer引擎:查询优化
- 根据AST优化产生最优执行计划(Plan Tree);
- 3)Executor引擎:查询执行
- 根据查询计划,完成数据读取、处、写入操作;
2、事务引擎:处理事务一致性、并发、读写隔离等;
3、存储引擎:内存中的数据缓存区、数据文件、日志文件;
3.2 SQL引擎
3.2.1 SQL引擎-Parse
词法分析、语法分析、语义分析;
- 1)词法分析:
- 将一条SQL语句对应的字符串分割为一个个token,这些token可以简单分类;
- 2)词法分析:
- 把此法分析的结果转为语法数,根据语法规则匹配SQL语句中关键字,最终输出一个结构化的数据结构;
- 3)语义分析:
- 对语法树的信息进行合法性校验;
3.2.2 SQL引擎-Optimizer
1、基于规则的优化(RBO-Rule Base Optimizer)
2、基于代码的优化(CBO Cost Base Optimizer)
3.2.3 SQL引擎-Executor
1、火山模型
- 优点:模块抽象独立化,相互无耦合;逻辑结构简单;
- 缺点:每计算一条数据有多次函数调用开销,导致CPU效率不高;
2、向量化
- 每次操作计算的不再是一行数据,而是一批batch数据;
- 优点:函数调用数减少;CPU cache缓存命中率更高;利用SIMD(single instruction multi data)机制;
3、编译执行
- 一个main包含所有操作,函数调用减少了,但是重复代码增多;
- 解决方法:动态编译,
- 代码生成之后数据库运行时仍然是一个for循环,只不过这个循环内部的代码从简单的一个虚函数调用plan.next)展开成了一系列具体的运算逻辑,这样数据就不用再各个operator之间进行传递,而且有些数据还可以直接被存放在寄存器中,进一步提升系统性能。整个操作有点像inline函数,把所有的操作inline到—个函数中去。 LLVM动态编译执行技术,根据优化器产生的计划,动态的生成执行代码。
3.3 存储引擎-InnoDB
3.3.1 存储引擎-Buffer Pool
1、问题
- 当buffer pool里的页面都被使用之后,再需要换存其他页面怎么办?淘汰已有的页面
- 基于什么规则淘汰:淘汰那个最近一段时间最少被访问过的缓存页了,这种思想就是典型的LRU算法了。
2、LRU算法
- 普通的LRU算法存在缺陷,考虑我们需要扫描100GB的表,而我们的buffer pool只有1GB,这样就会因为全表扫描的数据量大,需要淘汰的缓存页多,导致在淘汰的过程中,极有可能将需要频繁使用到的缓存页给淘汰了,而放进来的新数据却是使用频率很低的数据。
- MySQL确实没有直接使用LRU算法,而是在LRU算法上进行了优化。
3、MYSQL优化
- MySQL的优化思路就是:对数据进行冷热分离,将LRU链表分成两部分,一部分用来存放冷数据,也就是刚从磁盘读进来的数据,另—部分用来存放热点数据,也就是经常被访问到数据。
- 当从磁盘读取数据页后,会先将数据页存放到LRU链表冷数据区的头部,如果这些缓存页在1秒之后被访问,那么就将缓存页移动到热数据区的头部;如果是1秒之内被访问,则不会移动,缓存页仍然处于冷数据区中。淘汰时,首先淘汰冷数据区。
3.3.2 存储引擎-Page
3.3.3 存储引擎-B+树
3.4 事务引擎
3.4.1 事务引擎-Atomicity 与 Undo Log
- 需要记录数据修改前的状态,—边在事务失败时进行回滚。 undo log是逻辑日志,记录的是数据的增量变化,它的作用是保证事务的原子性和事务并发控制。可以用于事务回滚,以及提供多版本机制(MvCC),解决读写冲突和—致性读的问题。
3.4.2 事务引擎-Isolatoin 与 锁
- 读写互不阻塞,MVCC机制!!
3.4.3 事务引擎-Durability 与 Redo Log
一致性一般通过业务逻辑代码保证实现!