微信 SQLite 数据库修复实施

1、前言

强烈,微信在后台服务器不保留聊天记录,微信在活动客户端具备的聊天记录都存储在一个
SQLite
数据库中,一旦那个数据库损坏,将会丢掉用户多年的聊天记录。而我辈监控到现网的损坏率是0.02%,也就是每
1w 个用户就有 2
个会赶上数据库损坏。考虑到微信那样庞大的用户基数,那个损坏率就很要紧了。更严重的是大家用的合法修复算法,修复成功率只有30%。损坏率高,修复率低,那三个难点都亟需我们起始解决。

2、SQLite 损坏原因及其优化

咱俩先是来看 SQLite
损坏的案由,SQLite官网(http://www.sqlite.org/howtocorrupt.html)上列出以下几点%E4%B8%8A%E5%88%97%E5%87%BA%E4%BB%A5%E4%B8%8B%E5%87%A0%E7%82%B9):

  • 文本错写
  • 文件锁 bug
  • 文件 sync 失败
  • 设备损坏
  • 内存覆盖
  • 操作系统 bug
  • SQLite bug

只是大家经过征集到的大量案例和日志,分析出实际移动端数据库损坏的真的原因实在就3个:

  • 空间欠缺
  • 装备断电
  • 文件 sync 失败

咱俩须求针对那几个原因依次举办优化。

2.1、优化空间占据

先是大家来优化微信的半空中占据难点。在那以前微信的部分工作也做了空间清理,例如朋友圈会自动删除7天前缓存的图片。可是总的来说对文本空间的采纳紧缺一个大局把控,全靠各样业务自觉。我们需求做得更积极主动,要让开发人士意识到用户的贮存空间是难得的。大家应用以下格局:

  • 事情文件先申请后拔取,如果某个文件没有申请就使用了,会被电动扫描出来并删除;
  • 各样业务文件都要表明有效期,是一天、一个星期、一个月或者永远存储;
  • 过期文件会被电动清理。

图片 1

对于微信之外的半空中占据,例如相册、视频、其他App的空中占据,微信本身是做不了什么事情的,大家得以提醒用户展开空间清理:

图片 2

2.2、优化文件 sync

2.2.1、synchronous = FULL

安装SQLite的文书同步机制为全同台,亦即必要各类事物的写操作是真的flush到文件里去。

2.2.1、fullfsync = 1

透过与苹果工程师的交换,我们发现在 iOS 平台下还有 fullfsync
(https://www.sqlite.org/pragma.html#pragma_fullfsync)
那么些选项,能够严刻保障写入顺序跟提交顺序一致。设备开发商为了测评数据赏心悦目,往往会对交付的数量开展重排,再统一写入,亦即写入顺序跟App提交的次第不雷同。在好几意况下,例如断电,就可能导致写入文件不同的气象,导致文件损坏。

2.3、优化职能

多管齐下之后,大家成功将损坏率下降了大体上多;DB损坏照旧无法完全防止,咱们依然得提升修复成功率。

图片 3

3、SQLite 修复逻辑优化

3.1、master 表

第一大家来看 SQLite 的架构。SQLite 使用 B+树 存储一个表,整个 SQLite
数据库就是这么些 B+树 组成的老林。对于每个表的元数据(表名、根节点地址、表
scheme 等),都记录在一个叫 sql_master 的表中。这个 sql_master
表(下简称 master 表) 本身也是一个 B+树 存储的普通表。

图片 4

3.2、官方修复算法率低下原因

合法修复算法是这么一个流程:从 master
表中读出一个个表的音讯,按照根节点地址和创表语句来 select
出表里的数据,能 select 多少是不怎么,然后插入到一个新 DB 中。要注意的是
master 表他自个儿也是一个 B+树 形式的普通表,DB
第0页就是她的根节点。那么一旦 master
表某个节点损坏,那么些节点下边记录的表就都恢复生机持续。更坏的图景是 DB
第0页损坏,那么一切 master
表都读不出来,就导致整个DB都过来败北。那就是法定修复算法成功率这么低的原因,太依仗
master 表了。

3.3、备份 master 表

那么最自然的想法,自然是别的备份一份 master
表了,也不须要用B+树,间接用数组体系化存储就好。我们只需求每隔一段时间轮询
master 表,看看近期有没有增删 table,有的话就全量备份。

3.3.1、备份时机

此间有个担忧,就是普普通通数据表的插入会不会导致表的根节点发生变化,也就是说
master
表会不会频仍变更,倘诺生成很频仍的话,大家就不可以几乎地拓展轮询方案了。通过分析源码,大家发现
SQLite 里面 B+树 算法的已毕是 向下差别的,也就是说当一个叶子页满了须要分化时,原来的纸牌页会成为其中节点,然后新申请多少个页作为他的纸牌页。那就确保了根节点一旦定下来,是再也不会变动的。实际的代码调试也作证了俺们以此猜想。所以说
master
表只会在新创制表或者去除一个表时才会暴发变化,大家完全可以行使定时轮询方案。

3.3.2、备份文件有效性

接下去的难点是既然 DB
可以毁掉,那么那一个备份文件也会毁掉,咋办吧?大家选用了 双备份
的体制。具体来说就是会有新旧八个备份文件,每个文件头都添加 CRC
校验;每一次备份时,从四个备份文件中选出一个举办覆盖。具体怎么选呢?优先选损坏那多少个备份文件,假若七个都灵验,那么就选相对较旧的。那就保证了即使这一次写入导致文件损坏,还有其余一份备份可以用。那几个做法跟
Realm 标榜的
MVCC(多版本出现控制)的做法有异曲同工之妙,相当于认可新写入的文本有效之后,才使用新写入的公文,否则照旧持续用旧的实用的文件。

眼前提到 DB
损坏的一个科普现象是空间欠缺,那种境况下还要分配文件空间给备份文件也是会破产的。为了化解这几个标题,大家利用
预先分配空间 的做法,初叶值是 32K,大致可存 750
个表的元音讯,后续则根据32K的倍数举行压实。

3.4、优化职能

经过备份 master 表,大家中标将修复成功率提升了一倍多。

图片 5

4、其他

透过这么些优化,大家增强了微信聊天记录存储的可相信性。这几个优化实践,会同以前在出现品质方面的优化实践(微信iOS
SQLite源码优化实践),将会联合到微信即将开源的 WCDB(WeChat
Database)组件中。大家正在开展紧张的代码整理工作,争取在 2017 年年中开源
WCDB。


越多精粹内容欢迎关心腾讯 Bugly的微信公众账号:

图片 6

腾讯
Bugly
是一款专为移动开发者打造的质量监督工具,帮忙开发者快捷,便捷的定位线上选取崩溃的情事以及缓解方案。智能合并功能协理开发同学把每一天上报的数千条
Crash
依照根因合并分类,天天早报会列出影响用户数最多的倒台,精准定位成效支持开发同学定位到出题目的代码行,实时反馈可以在公布后急忙的垂询应用的身分景况,适配最新的
iOS, Android 官方操作系统,鹅厂的工程师都在应用,快来参加大家呢!

网站地图xml地图