SQLite3 存储以及ACID原理

我一直想知道如何处理磁盘存储,最近学习了一下SQLite3的做法,这是学习笔记。

首先多亏了操作系统的抽象,对于一个磁盘上文件,我们可以简单的想象成 是一个无限大的数组,基于这一层认知,我们就知道,如果我们想要分配和 管理这一个数组,那么就需要有一个系统,专门负责分发和回收。

这其实和内存管理是一致的,常见的内存管理通常也会把内存划分为不同大小的块, 然后分发给程序,管理磁盘则也是一样,可以把数组划分为不同大小的块, 然后分发给程序。

只不过,区别在于,对于内存操作,我们的最小修改和读取单位可以是byte, 而对于磁盘,则不行,机械硬盘通常有一个最小的读写单位,叫做sector(扇区), 一般来说,大小为512bytes,对于较新的磁盘,一般都是4096bytes。

如果SQLite3想要使用不同大小的page,也不是不可以,不过对于数据库来说, 最好是使用相同大小的page,管理page的模块就叫pager。

SQLite3 把所有的数据都存储在一个文件里,文件的开头100byte,存储了 数据库的元信息,比如格式,page的大小,文件格式版本等等。

SQLite3 file format

SQLite3 file header

SQLite3 使用B+树来保存PRIMARY INDEX及数据,用B树来保存SECONDARY INDEX。

ACID

ACID是数据库事务的四个特性:

  • 原子性(atomicity,或称不可分割性
  • 一致性(consistency)
  • 隔离性(isolation,又称独立性)
  • 持久性(durability)

SQLite3 通过对整个数据库文件上锁,外加journal/WAL来保证这四个特性。

SQLite3 的锁主要分为读和写,读锁是可以共存的,但是写锁是互斥的,也就是说, 同时只有一个地方能写入,这也就保证了隔离性,再加上日志,就实现了ACID。

对于 journal 和 WAL 是如何工作的,分别可以参考 journalWAL 的文档。


ref:


微信公众号
关注公众号,获得及时更新

更多文章
  • Haskell简明教程(二):从命令式语言进行抽象
  • Haskell简明教程(一):从递归说起
  • 2017年必装的VIM插件推荐
  • TCP/IP简明教程 - 从零构建TCP/IP协议(二)连接,断开与拥塞控制
  • TCP/IP简明教程 - 从零构建TCP/IP协议(这次叫PCT协议)
  • Lua Manual 阅读笔记
  • Golang Map 源码阅读与分析
  • MySQL 零碎知识 - MySQL必知必会
  • Golang slice 源码阅读与分析
  • 经典好书推荐(2017)
  • Golang log库 源码阅读与分析
  • 毕业后一年
  • ansible 简明教程
  • 自己写个搜索引擎
  • HTTP 路由的两种常见设计形式