关系型数据库工做原理简述

关系型数据库工做原理简述 翻译自 VLADMIHALCEA 的 How does a relational database work,从属于笔者的 服务端基础架构入门与实践。本文只是寥寥数言的关系型数据库工做流程简述,关于关系型数据库工做原理的详细介绍建议阅读 ChristopheHow does a relational database workgit

概述

在我撰写 High-Performance Java Persistence training 一书时,我逐步认识到让读者明白关系型数据库工做原理会是了解如何构建高性能的 Java 持久化存储的重要基石。不过关系型数据库中的事务相关的重要概念:原子性、持久性以及检查点等等也是至关绕人。而本文中我但愿以相对高屋建瓴的方式来解释关系型数据库内部工做原理,也会涉及一些数据库实现细节。github

Data Pages

访问磁盘中的数据每每速度较慢,换言之,内存中数据的访问速度仍是远快于 SSD 中的数据访问速度。基于这个考量,基本上全部数据库引擎都尽量地避免访问磁盘数据。而且不管数据库表仍是数据库索引都被划分为了固定大小的数据页(譬如 8 KB)。当咱们须要读取表或者索引中的数据时,关系型数据库会将磁盘中的数据页映射入存储缓冲区。当咱们须要修改数据时,关系型数据库首先会修改内存页中的数据,而后利用 fsync) 这样的同步工具将改变同步回磁盘中。数据库

Undo log

因为同时可能由多个事务并发地对内存中的数据进行修改,所以关系型数据库每每须要依赖于某个并发控制机制(2PL 或者 MVCC)来保证数据一致性。所以,当某个事务须要去更改数据表中某一行时,未提交的改变会被写入到内存数据中,而以前的数据会被追加写入到 undo log 文件中。数据结构

Oracle 或者 MySQL 中使用了所谓 undo log 数据结构,而SQL Server 中则是使用 transaction log 完成此项工做。PostgreSQL 并无 undo log,不过其内建支持所谓多版本的表数据,即同一行的数据可能同时存在多个版本。总而言之,任何关系型数据库都采用的相似的数据结构都是为了容许回滚以及数据的原子性。架构

若是当前运行的事务发生了回滚,undo log 会被用于重建事务起始阶段时候的内存页。并发

Redo Log

某个事务提交以后,内存中的改变就须要同步到磁盘中。不过并非全部的事务提交都会马上触发同步,太高频次的同步反而会对应用性能形成损伤。不过根据 ACID 原则,提交以后的事务必需要保证持久性,也就是即便此时数据库引擎宕机了,提交以后的更改也应该被持久化存储下来。这里关系型数据库就是依靠 redo log 来达成这一点,它是一个仅容许追加写入的基于磁盘的数据结构,它会记录全部还没有执行同步的事务操做。相较于一次性写入固定数目的数据页到磁盘中,顺序地写入到 redo log 会比随机访问快上不少。所以,关于事务的 ACID 特性的保证与应用性能之间也就达成了较好的平衡。该数据结构在 Oracle 与 MySQL 中就是叫 redo log,而 SQL Server 中则是由 transaction log 执行,在 PostgreSQL 中则是使用 Write-Ahead Log( WAL )。
下面咱们继续回到上面的那个问题,应该在什么时候将内存中的数据写入到磁盘中。关系型数据库系统每每使用检查点来同步内存的脏数据页与磁盘中的对应部分。为了不 IO 阻塞,同步过程每每须要等待较长的时间才能完成。所以,关系型数据库须要保证即便在全部内存脏页同步到磁盘以前引擎就崩溃的时候不会发生数据丢失。一样地,在每次数据库重启的时候,数据库引擎会基于 redo log 重构那些最后一次成功的检查点以来全部的内存数据页。mvc

总结

上面咱们简要讨论的这些原则与考虑都是为了保证基于磁盘的存储的较高吞吐量的同时保证数据一致性。其中,undo lo 主要用于提供原子性(容许回滚),而 redo log 则是保证磁盘页的不可变性。ide

相关文章
相关标签/搜索