# 10.9 只读数据库（Read-only Database）

如果你查看论文的图3，你可以发现，Aurora不仅有主数据库实例，同时多个数据库的副本。对于Aurora的许多客户来说，相比读写查询，他们会有多得多的只读请求。你可以设想一个Web服务器，如果你只是查看Web页面，那么后台的Web服务器需要读取大量的数据才能生成页面所需的内容，或许需要从数据库读取数百个条目。但是在浏览Web网页时，写请求就要少的多，或许一些统计数据要更新，或许需要更新历史记录，所以读写请求的比例可能是100：1。所以对于Aurora来说，通常会有非常大量的只读数据库查询。

对于写请求，可以只发送给一个数据库，因为对于后端的存储服务器来说，只能支持一个写入者。背后的原因是，Log需要按照数字编号，如果只在一个数据库处理写请求，非常容易对Log进行编号，但是如果有多个数据库以非协同的方式处理写请求，那么为Log编号将会非常非常难。

但是对于读请求，可以发送给多个数据库。Aurora的确有多个只读数据库，这些数据库可以从后端存储服务器读取数据。所以，图3中描述了，除了主数据库用来处理写请求，同时也有一组只读数据库。论文中宣称可以支持最多15个只读数据库。如果有大量的读请求，读请求可以分担到这些只读数据库上。

![](/files/-MFnEdpRirRRHWHhnc7m)

当客户端向只读数据库发送读请求，只读数据库需要弄清楚它需要哪些data page来处理这个读请求，之后直接从存储服务器读取这些data page，并不需要主数据库的介入。所以只读数据库向存储服务器直接发送读取page的请求，之后它会缓存读取到的page，这样对于将来的一些读请求，可以直接根据缓存中的数据返回。

![](/files/-MFnPeeORZSXv5oMhqi3)

当然，只读数据库也需要更新自身的缓存，所以，Aurora的主数据库也会将它的Log的拷贝发送给每一个只读数据库。这就是你从论文中图3看到的蓝色矩形中间的那些横线。主数据库会向这些只读数据库发送所有的Log条目，只读数据库用这些Log来更新它们缓存的page数据，进而获得数据库中最新的事务处理结果。

![](/files/-MFnPnjaLWSsyNba5Bip)

这的确意味着只读数据库会落后主数据库一点，但是对于大部分的只读请求来说，这没问题。因为如果你查看一个网页，如果数据落后了20毫秒，通常来说不会是一个大问题。

这里其实有一些问题，其中一个问题是，我们不想要这个只读数据库看到未commit的事务。所以，在主数据库发给只读数据库的Log流中，主数据库需要指出，哪些事务commit了，而只读数据库需要小心的不要应用未commit的事务到自己的缓存中，它们需要等到事务commit了再应用对应的Log。

另一个问题是，数据库背后的B-Tree结构非常复杂，可能会定期触发rebalance。而rebalance是一个非常复杂的操作，对应了大量修改树中的节点的操作，这些操作需要有原子性。因为当B-Tree在rebalance的过程中，中间状态的数据是不正确的，只有在rebalance结束了才可以从B-Tree读取数据。但是只读数据库直接从存储服务器读取数据库的page，它可能会看到在rebalance过程中的B-Tree。这时看到的数据是非法的，会导致只读数据库崩溃或者行为异常。

论文中讨论了微事务（Mini-Transaction）和VDL/VCL。这部分实际讨论的就是，数据库服务器可以通知存储服务器说，这部分复杂的Log序列只能以原子性向只读数据库展示，也就是要么全展示，要么不展示。这就是微事务（Mini-Transaction）和VDL。所以当一个只读数据库需要向存储服务器查看一个data page时，存储服务器会小心的，要么展示微事务之前的状态，要么展示微事务之后的状态，但是绝不会展示中间状态。

以上就是所有技术相关的内容，我们来总结一下论文中有意思的地方，以及我们可以从论文中学到的一些东西。

* 一件可以学到的事情其实比较通用，并不局限于这篇论文。大家都应该知道事务型数据库是如何工作的，并且知道事务型数据库与后端存储之间交互带来的影响。这里涉及了性能，故障修复，以及运行一个数据库的复杂度，这些问题在系统设计中会反复出现。
* 另一个件可以学到的事情是，Quorum思想。通过读写Quorum的重合，可以确保总是能看见最新的数据，但是又具备容错性。这种思想在Raft中也有体现，Raft可以认为是一种强Quorum的实现（读写操作都要过半服务器认可）。
* 这个论文中另一个有趣的想法是，数据库和存储系统基本是一起开发出来的，数据库和存储系统以一种有趣的方式集成在了一起。通常我们设计系统时，需要有好的隔离解耦来区分上层服务和底层的基础架构。所以通常来说，存储系统是非常通用的，并不会为某个特定的应用程序定制。因为一个通用的设计可以被大量服务使用。但是在Aurora面临的问题中，性能问题是非常严重的，它不得不通过模糊服务和底层基础架构的边界来获得35倍的性能提升，这是个巨大的成功。
* 最后一件有意思的事情是，论文中的一些有关云基础架构中什么更重要的隐含信息。例如：
  * 需要担心整个AZ会出现故障；
  * 需要担心短暂的慢副本，这是经常会出现的问题；
  * 网络是主要的瓶颈，毕竟Aurora通过网络发送的是极短的数据，但是相应的，存储服务器需要做更多的工作（应用Log），因为有6个副本，所以有6个CPU在复制执行这些redo Log条目，明显，从Amazon看来，网络容量相比CPU要重要的多。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mit-public-courses-cn-translatio.gitbook.io/mit6-824/lecture-10-cloud-replicated-db-aurora/10.9-zhi-du-shu-ju-ku-readonly-database.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
