# RocksDB: 写入

__*MemTable*__
__*immutable MemTable*__
__*SST*__
__*RocksDB 写流程*__

![`smart`](./student-guide/diagram/RocksDBWrite01_aa_001_20220511.png)
-------------------------------------------------------------
下面我们来看一下 `RocksDB` 的写操作是如何进行的,从而理解 `TiDB` 数据库通过 `RocksDB` 是如何持久化数据的,`RocksDB` 采用 `LSM Tree` 的数据结构来存储 `key value` 数据,`LSM Tree` 会将所有的数据插入、修改和删除等操作保存在内存之中,当此类操作达到一定的数据量后,再批量地写入到磁盘中。而在写入磁盘时,会和以前的数据做合并。在合并过程中,不会像 `B+ Tree`一样,在原数据的位置上修改,而是直接插入新的数据,从而避免了`Random Write`。

`LSM Tree` 的结构是横跨内存和磁盘的,包含 `MemTable`、`immutable MemTable`、`SSTable` 等多个部分,我们以图中的一次写入操作来说明 `LSM Tree` 和其相关组件的工作流程。

1. 先通过 `WAL` 的方式备份到磁盘中,以防数据因为内存掉电而丢失（预写式日志 `Write-ahead Logging`, 缩写 `WAL` 是关系数据库系统中用于提供原子性和持久性的一系列技术之一 ）。在使用 `WAL` 的系统中,所有的修改在提交之前都要先写入日志文件中,`sync-log = true` 表示写入会调用 `fsync`,将 `WAL` 日志文件持久化道磁盘中,而不是操作系统缓存中。

2. `WAL` 完成后,就会写数据到 `MemTable` 中,`MemTable` 是一个内存数据结构,它保存了落盘前的数据。`MemTable` 可以使用跳跃表或者搜索树等数据结构来组织数据以保持数据的有序性。
`MemTable` 同时服务于读和写。新的写入总是将数据插入到 `MemTable`,读取操作在查询 `SST` 文件前总是要查询 `MemTable`,因为 `MemTable` 里面的数据总是最新的。

3. 当 `MemTable` 达到一定的数据量（`write_buffer_size` 的大小）后, `MemTable` 会转化成为 `immutable MemTable`（`immutable MemTable` 在内存中是不可修改的数据结构,它是将 `MemTable` 转变为 `SSTable (Sorted String Table)` 的一种中间状态。目的是为了在转存过程中不阻塞写操作。
   - 写操作可以由新的 `MemTable` 处理,而不会因为锁住 `MemTable` 而等待）,同时会创建一个新的 `MemTable` 来处理新的数据。一个后台线程会把这个 `MemTable` 的内容保存到一个 `SST` 文件, 是 `LSM Tree` 在磁盘中的数据的结构, `MemTable` 中的数据最终都会被转化为 `SSTable` 并保存在磁盘中。然后, 这个 `MemTable` 就可以被销毁了,同时携带有跟这个 `MemTable` 相关数据的 `WAL` 文件也可以被删除。
   - 默认出现 1 个 `immutable MemTable` 就会触发磁盘保存 ,5 个 `immutable Memtable` 会触发 `write stall`。


