CMU 15-445 数据库课程第三课文字版 - 存储1(中)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: CMU 15-445 数据库课程第三课文字版 - 存储1(中)

还有一些系统调用可以让我们来告诉操作系统如何操作 mmap 内存:


image.png


  • madvise:告诉操作系统你会怎么读取,是随机读取还是顺序读取
  • mlock:防止操作系统将某些页与物理内存解绑
  • msync:告诉操作系统将某些页刷入磁盘

主流数据库(比如 MySQL,Postgres,Oracle,sqlserver 等等)都没有使用 mmap,那些在使用的大部分也正在考虑替换掉 mmap。

所以,我们总结下:


image.png


如果你将内存管理全权交给操作系统,操作系统可能会做出一些对于你的性能有损的决策,DBMS 通常都想自己控制内存管理策略,这样就可以带来:

  • 根据当前数据库存储格式以及用户请求,决策脏页刷入磁盘的顺序,提高效率
  • 根据存储结构以及用户请求,缓存预取提高查询速度
  • 根据存储结构优化缓冲过期策略
  • 多线程管理


3. 数据库文件存储结构-存储管理(Storage Manager)


image.png


数据库其实就是磁盘上的一个或者多个文件,例如 sqlite 整个数据库就在一个文件中,大多数其他的数据库例如 MySQL 则是分了不同文件存储。sqlite 本身就是轻量级的系统,MySQL 这种一般考虑存储性能以及限制等会划分成不同的文件,在现在的文件系统中,文件大小限制已经不太是一个考虑因素了,你甚至可以有超 PB 的文件,但是像是那种老的文件系统例如 fat32 那种,最大只支持 2GB 大小。我们这里提到了文件系统(File System),文件系统其实就是操作系统给我们提供的操作文件的 api,我们通过这些 api 操作文件(文件其实就是一堆存储上面的块)。大部分数据库是依赖操作系统提供的文件系统的,曾经有一些厂商提供了自己原生的文件系统专门用于自己的数据库产品使用,但是这样就丧失了迁移以及部署在云上的灵活性。

我们这里要实现的就是DBMS的存储管理器(Storage Manager)


image.png


存储管理器负责管理上面提到的数据库文件,我们在这里会向操作系统发送读和写请求,操作系统会调度这些读写。一些比较高端的系统,还会优化这些系统调度,即在这文件系统上抽象出来一个中介层,在这个中阶层管理本由操作系统的管理的调度,比如这个中阶层知道会有多线程发多请求写互相临近的块,这个中阶层会组合在一起形成一个写请求。这里我们就不做这个了,太复杂了。

在这些文件里面,是由(page)组织起来的,由一组页组成。我们会以页的维度记录这些页的读写(例如哪些页还有空间可以存储新数据,哪些页里面有脏数据还没刷入磁盘,哪些页已经完全满了)


image.png


页其实就是固定大小的数据块,页中存储数据库中所有相关的数据,例如元组数据、元数据、索引还有日志记录等等。但是我们总是尽量将内容存储在单个页中,并且页需要是自包含的,即关于如何解释和理解页内容,所需要的所有信息都必须存储在页本身中。这样,即使丢失任何一页,也不会影响其他任何一页的解析和使用。如果你把元数据存储与元组数据分开存储在不同的页,如果元数据页丢失或者损坏了,那么元组数据页也就无法解析了。这种自包含的设计,对于容灾更好

虽然不同种类的数据(例如元组数据、元数据、索引还有日志记录)都是存储在页中,但是在同一页内一般不会存储不同类型的数据。有一些研究型的数据库可能会在同一页中存储不同类型的数据,但是大部分系统都没有这么做。

每个页都有唯一的标识符即页 ID(Page ID)。我们使用这个唯一标识符形成一个中间层,在这个中间层维护 Page ID 与实际存储的文件的位置的映射,通过 Page ID 就能定位到对应的文件位置并读取这个页。同时如果我们移动了页(例如我们想扩展存储,压缩存储使用等等),Page ID 不会变,只是修改了文件位置,这比直接使用文件位置存储要方便很多。这样 DBMS 的其它层就不用关心这个,只记录 Page ID 就可以,我们在修改页位置的时候不用告知其他层同时修改。


image.png


我们有很多不同的层面有页这个概念:

  • 硬件存储页(Hardware Page):通常是 4KB。也就是如果你写的数据在 4KB 以内,那么就能保证原子性,不会发生写了一部分掉电导致只写入了一部分成功的情况,只会要么全成功或者全写入失败
  • 操作系统页(OS Page):通常也是 4KB
  • 数据库页(Database Page):通常是 512~16KB,例如 MySQL InnoDB 页大小默认 16KB,目前 8.0 可以配置成 4KB 8KB 16KB 32KB 64KB。在一些比较高端的系统,你甚至可以对于不同类型的页设置不同的页大小,例如元组数据页大小比较小,索引页大小调整的比较大。

将数据库页调大,那么单页就可以保存更多的数据,那么后面会提到的页目录大小就会降低,页目录是用来找所有页的位置的存储,一般会一直存在于内存中,页目录越小,那么 CPU 缓存命中率越高。并且更多的数据在同一页上面,读取数据也是一页一页读取,这样对于缓存预取也有好处。但是相应的,写入也是一页一页刷入,带来的写入消耗也更大。这就是为啥那些商用的数据库允许你调整页大小的原因。


image.png


那么如何设计文件页结构呢,一般有三种:

  • 堆文件组织(Heap File Organization):这是最常用的,我们也会主要研究这种。每种关系存储到一个单独的文件,文件中的记录是无顺序的。
  • 顺序文件组织(Sequential File Organization):所有文件里面的记录内容,都按照记录的某个属性值的一定顺序排序好。
  • 哈希散列文件组织(Hashing File Organization):使用记录的某些属性计算哈希值,决定存储在文件的哪个位置。


image.png


数据库堆文件是一个无序的页面集合,其中元组数据可以随机顺序存储。其实关系模型中,也没有对元组定义任何顺序。我们所要实现的就是针对页操作的增删改查 API,以及遍历所有页的 API。

同时,我们需要一些元数据追踪哪些页还有剩余空间,这样在我们需要插入新数据的时候就能快速定位到在哪里插入。

一般我们通过页目录(Page)这种方式设计堆文件中的结构,但是首先我们先来通过链表(Linked List)设计下文件结构来看下为何这种方式是愚蠢的


image.png


如果使用链表设计的话,一般我们会维护一个 Header 页,在这个页 里面我们维护两个指针,一个指针是指向所有还有剩余空间的页链表的指针,另一个指针指向的是已经被填充满的页链表指针。这两个链表都是双向链表,我们可能顺序遍历也可能逆序遍历:顺序遍历一般用于找合适的位置比如找还有足够容纳我们要插入数据空间的页,逆序遍历一般用于移动。这并不是一个比较好的设计方式,主要是插入与更新的效率比较低


image.png


这是使用更多的设计方式,即页目录。我们维护一个专门存储目录的页,在这个目录中维护页 ID 到具体文件位置的偏移量的映射,可以简单把它理解成一个 key 为页 ID value 为文件位置偏移的哈希表。并且在这里还会维护页的空闲空间信息,这样在插入的时候,我们可以直接通过页目录直接定位到要插入的页。但是这样也带来了原子更新的问题,即页的空闲空间信息与插入数据是否在一个原子操作内。但是由于这个两个页的操作,硬件层面上我是很难保证两页更新是原子性的,所以我们需要额外的机制在数据库重启的时候检查是否有这些未完成的写入,这在后面讲恢复与日志的章节的时候会说到。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
4月前
|
存储 关系型数据库 MySQL
MySQL——数据库备份上传到阿里云OSS存储
MySQL——数据库备份上传到阿里云OSS存储
173 0
|
2月前
|
存储 关系型数据库 MySQL
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
PACS系统 中 dicom 文件在mysql 8.0 数据库中的 存储和读取(pydicom 库使用)
34 2
|
3月前
|
SQL 关系型数据库 MySQL
学成在线笔记+踩坑(3)——【内容模块】课程分类查询、课程增改删、课程计划增删改查,统一异常处理+JSR303校验
课程分类查询、课程新增、统一异常处理、统一封装结果类、JSR303校验、修改课程、查询课程计划、新增/修改课程计划
学成在线笔记+踩坑(3)——【内容模块】课程分类查询、课程增改删、课程计划增删改查,统一异常处理+JSR303校验
|
3月前
|
前端开发 应用服务中间件 API
|
3月前
|
存储 SQL 专有云
支持配置审计日志的存储数据库
审计日志作为企业监管平台的重要依据,同时也是“等保三级”认证的必要考察项之一。Dataphin V4.3版本支持设置平台日志的存储数据源,帮助用户快速获取审计日志,同时介绍了不同部署模式的Dataphin如何查看审计日志的方法。
117 5
|
3月前
|
存储 NoSQL 关系型数据库
可以存储文件的数据库有哪些?
可以存储文件的数据库有哪些?
128 6
|
3月前
|
存储 NoSQL 关系型数据库
可以存储文件的数据库有哪些?
可以存储文件的数据库有哪些?
507 0
|
4月前
|
存储 缓存 负载均衡
带你认识DM 共享存储数据库集群
带你认识DM 共享存储数据库集群
82 3
|
4月前
|
存储 C# 关系型数据库
“云端融合:WPF应用无缝对接Azure与AWS——从Blob存储到RDS数据库,全面解析跨平台云服务集成的最佳实践”
【8月更文挑战第31天】本文探讨了如何将Windows Presentation Foundation(WPF)应用与Microsoft Azure和Amazon Web Services(AWS)两大主流云平台无缝集成。通过具体示例代码展示了如何利用Azure Blob Storage存储非结构化数据、Azure Cosmos DB进行分布式数据库操作;同时介绍了如何借助Amazon S3实现大规模数据存储及通过Amazon RDS简化数据库管理。这不仅提升了WPF应用的可扩展性和可用性,还降低了基础设施成本。
88 0
|
4月前
|
存储 小程序 关系型数据库
原生小程序 获取手机号并进行存储到mysql数据库
原生小程序 获取手机号并进行存储到mysql数据库

热门文章

最新文章

下一篇
无影云桌面