14

union store 数据一致性以及约束检查

 4 years ago
source link: https://www.zenlife.tk/unionstore-contract.md
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

union store 数据一致性以及约束检查

2019-01-26

在 TiDB 里面,事务的所有操作都会先临时缓存在本地内存,直到事务提交的时候,通过 2PC 将事务的所有修改整体提交。

这样会遇到一个问题,后面的操作需要 “看见” 前面的操作的修改。比如插入 a,再读取 a,这时需要读到刚刚插入的 a。由于前面的插入并没有真正写下去,我们读的时候需要做一个融合:优先读本地缓存,读不到的情况下,再穿透缓存去读下面的存储。把这些东西封装起来,让调用者只管当它是一个 store,我们把这个封装的代码叫 union store。

union store 概念上尽管很简单,但是实际的代码还是挺乱的。中间穿插着 dirty table,binlog,事务状态等等东西,维护起来容易出错。我前面写过一篇编写安全的代码,是思考理想的情况下,应该怎么样让代码更健壮。但是现实与理想相去甚远。这里很容易弄坏数据,出现数据不一致,对于数据库,数据错了就是灾难。然而没人能保证代码永无 bug。所以这次换一个角度:如何让 bug 不产生破坏性影响,让系统更健壮。

这应该算工程手段吧。可以先解释所谓的工程手段。

做个类比,我要写很多数据到磁盘,也不确定会不会中间有数据出错。于是可以写数据的时候,生成一份检验信息,把检验信息和数据一起写出去,然后验证。该过程并消灭掉中间写数据出错的可能性,但是捕获到出错的情况了。

再做个类比,就像写一个内存分配器,想保证代码完全没有 bug 并不容易。那么让定位 bug 更容易一些呢?可以把每次分配操作,在哪分配,分配了多少空间,全部记录下来,然后去重放操作。能复现就好查问题了。

回到正题,先分析下导致数据写坏的 bug 都是如何产生,比如写了数据没写索引;比如该缓存没有刷,上一次操作的缓存留到下一次了;或者错误处理没做好,有一半成功一半失败,导致部分残留了;比如更新的时候,读出错了,接着用读到的错误数据去写...

union store 看到的东西,都不是真实的,而是缓存融合真实存储后的一个视图。缓存融合的过程中,可能 bug 导致数据有问题。

约束检查是个这样的想法:所有操作过程中,都会产生一些假设。 我们把操作的假设 (contract) 全记录下来,提交缓存数据时,把 contract 一起提交下去验证。 就相当于,代码无 bug 的情况下,这些 contract 应该是满足的。 如果代码有 bug,就有可能捕获了。

举个具体点的例子,更新一条记录,会先读后写,更新数据和更新索引。那么,这个操作的 contract 就包含,老的索引数据存在,老的数据存在。如果是唯一索引,那么生成的 contract 还包括索引数据是不存在的。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK