这是我参与「第五届青训营」伴学笔记创作活动的第14天。
1 经典案例
1.1 从一场红包雨说起
每一年的春节,抖音上都会下一场温暖人心的红包雨~
从抖音的账户上扣除一个小目标;给羊老师的账户加上一个小目标。
1.2 RDBMS事务ACID
RDBMS事务:是由一组SQL语句组成的一个程序单元(Unit),它需要满足ACID特性。
ACID:原子性、一致性、隔离性、持久性。
1.3 红包雨 与 ACID
Case1:抖音的账户上扣了一个亿之后,假设服务器挂了,还没来得及羊老师账户加上一个亿。
两个操作要么同时成功,要么同时失败,不存在中间状态。
Case2:假设抖音的账户上只有0.5个亿,但是扣减1个亿的操作成功了。
每个操作都必须是合法的,账户信息应该从一个有效的状态。
Case3:羊老师从抖音抢了一个亿红包,又从头条抢了一个亿,两个转账同时进行,假设他们都以为是从零开始的。
Case4:抖音的账户上扣了一个亿,然后羊老师账户上加一个小目标,这个时候,如果服务器挂了:
持久性:操作更新成功之后,更新的结构应该永久性的保留下来,不会因为宕机等问题而丢失。
1.4 红包雨与高并发
Case5:全国14亿人,假设有10亿人同时开抢红包,每秒处理一个请求,那需要31年才能完成。春节完了,抖音可能也被大家嫌弃了。。。---高并发
1.5 红包雨与高可靠
Case6:假设除夕晚上正在愉快的从抖音身上“薅羊毛”,这时候服务器挂了,程序花了一个小时,头发都掉光了,终于修好了。这时候发现李谷一老师《难忘今宵》都组完了。“抖音宕机”秒上热搜。。。---高可靠、高可用
1.6 大家一起“薅羊毛”
2 发展历史
2.1 前DBMS时代-人工管理
在现代计算机发明出来以前,通过人工的方式进行数据记录和管理:
2.2 前DBMS时代-文件系统
1950s,现代计算机的雏形基本出现。1956年IBM发布了第一个的磁盘驱动器--Model 305 RAMAC,从此数据存储进入磁盘时代。在这个阶段,数据管理直接通过文件系统来实现。
2.3 DBMS时代
1960s,传统的文件系统已经不能满足人们的需要,数据管理系统应运而生。
DBMS:按照某种数据模型来组织、存储和管理数据仓库。
所以通常按照数据模型的特点将传统数据库系统分成网状数据库、层次数据库和关系数据库三类。
2.3.1 DBMS数据模型-网状模型
网状数据库所基于的网状数据模型建立的数据之间的联系,能反映现实世界中的信息的关联,是许多空间对象的自然表达形式。1964年,世界上第一个数据库系统---集成数据存储诞生于通用电气公司。IDS是世界上第一个网状数据库,奠定了数据库发展的基础,在当时得到了广泛的应用。在1970s网状数据库系统十分流行,在数据库系统产品中占据主导地位。
2.3.2 层次模型
1968年,世界上第一个层次数据库---信息管理系统(IMS),诞生于IBM公司,这也是世界上第一个大型商用的数据库系统。层次数据模型,即使用树形结构来描述实体及其之间关系的数据模型。
2.3.3 关系模型
1970年,IBM的研究员E.F.Codd博士发表了一篇名为的论文,提出了关系模型的概念,奠定了关系模型的理论基础。1979年Oracle首次将关系型数据库商业化,后续DB2,SAP Sysbase ASE,and inform等知名数据库产品也纷纷面世。
2.4 DBMS数据模型
2.5 SQL语言
1974年IBM的Ray Boyce和Don Chamberlin将Codd关系数据库的12条准则的数学定义以简单的关键字语法表现出来,里程碑式的提出了SQL语言。
语法风格接近自然语言;
高度非过程化;
面向集合的操作方式;
语言简洁,易学易用。
2.6 历史回顾
3 关键技术
3.1 一条SQL的一生
UPDATE account_table SET balance = balance -'小目标' WHERE name = '抖音'
3.2 SQL引擎
3.2.1 SQL引擎-Parser
解析器一般分为词法分析、语法分析、语义分析等步骤。
3.2.2 SQL引擎-Optimizer
为什么需要一个优化器?
SELECT * FROM A,B,C WHERE A.a1 = B.b1 and A.a1 = C.bi
基于规则的优化(RBD)
条件化简:
表连接优化:总是小表先进行连接
SELECT * FROM A,B,C WHERE A.a1 = B.b1 and A.a1 = C.b1;
Scan优化:唯一索引、普通索引、全表扫描。
数据库索引:是数据库管理系统中辅助数据结构,以协助快速查询、更新数据库表中数据,目前数据库中最常用的索引是通过B+树实现的。
基于代价的优化(CBD)
一个查询有多种执行方案,CBD会选择其中代价最低的方案去真正的执行。
什么是代价?
火山模型:
每个Operator调用Next操作,访问下层Operator,获得下层Operater返回的一行数据,经过计算之后,将这行数据返回给上层。
优点:每个算子独立抽象实现,相互之间没有耦合,逻辑结构简单。
缺点:每计算一条数据有多次函数调用开销,导致CPU效率不高。 3.2.3 SQL引擎-Executor 向量化:
优点:函数调用次数降低为1/N;CPU cache命中率更高;可以利用CPU提供的SIMD机制。
编译执行:
将所有的操作封装到一个函数里面,函数调用的代价也能大幅度降低。
用户SQL千变万化怎么办?难道要穷举用户的所有SQL,给每一个SQL都预先写好一个执行函数吗?
3.3 存储引擎
3.3.1 存储引擎-InnoDB
In-Memory:Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer
On-Disk: System Tablespace(ibdata1)、General Tablespaces(XXX.ibd)、Undo Tablespaces(XXX.ibu)、Temporary Tablespaces 3.3.2 存储引擎-Buffer Pool
3.3.3 存储引擎-Page
Header
delete_mask:标示此条数据是否被删除。
next_record:下一条数据的位置。
record_type:表示当前记录的类型。
3.3.4 存储引擎-B+ Tree
3.4 事务引擎
3.4.1 事务引擎-Atomicity与Undo Log
如何将数据库回退到修改之前的状态?
Undo Log是逻辑日志,记录的是数据的增量变化,利用Undo Log可以进行事务回滚,从而保证事务的原子性。同时也实现多版本并发控制(MVCC),解决读写冲突和一致性读的问题。
3.4.2 事务引擎-Isolation与锁
前情提要:羊老师从抖音抢了一个亿红包,又从头抢了一个亿,抖音和头条都要往羊老师的账户转一个亿,如果两个操作同时进行,发生冲突怎么办?
3.4.3 事务引擎-Isolation与MVCC
MVCC的意义:读写互不阻塞;降低死锁概率;实现一致性读。
3.4.4 事务引擎-Durability与Redo Log
如何保证事务结束后,对数据的修改永久的保存?
方案一:事务提交前页面写盘
方案二:WAL
redo log是物理日志,记录的是页面的变化,它的作用是保证事务持久化。如果数据写入磁盘前发生故障,重启Mysql后会根据redo log重做。