日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

微信 SQLite 数据库修复实践

發布時間:2024/4/17 数据库 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微信 SQLite 数据库修复实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1、前言

眾所周知,微信在后臺服務器不保存聊天記錄,微信在移動客戶端所有的聊天記錄都存儲在一個 SQLite 數據庫中,一旦這個數據庫損壞,將會丟失用戶多年的聊天記錄。而我們監控到現網的損壞率是0.02%,也就是每 1w 個用戶就有 2 個會遇到數據庫損壞??紤]到微信這么龐大的用戶基數,這個損壞率就很嚴重了。更嚴重的是我們用的官方修復算法,修復成功率只有 30%。損壞率高,修復率低,這兩個問題都需要我們著手解決。

2、SQLite 損壞原因及其優化

我們首先來看 SQLite 損壞的原因,SQLite官網(http://www.sqlite.org/howtocorrupt.html)上列出以下幾點:

  • 文件錯寫
  • 文件鎖 bug
  • 文件 sync 失敗
  • 設備損壞
  • 內存覆蓋
  • 操作系統 bug
  • SQLite bug

但是我們通過收集到的大量案例和日志,分析出實際上移動端數據庫損壞的真正原因其實就3個:

  • 空間不足
  • 設備斷電
  • 文件 sync 失敗

我們需要針對這些原因一一進行優化。

2.1、優化空間占用

首先我們來優化微信的空間占用問題。在這之前微信的部分業務也做了空間清理,例如朋友圈會自動刪除7天前緩存的圖片。但是總的來說對文件空間的使用缺乏一個全局把控,全靠各個業務自覺。我們需要做得更積極主動,要讓開發人員意識到用戶的存儲空間是寶貴的。我們采取以下措施:

  • 業務文件先申請后使用,如果某個文件沒有申請就使用了,會被自動掃描出來并刪除;
  • 每個業務文件都要申明有效期,是一天、一個星期、一個月還是永久存儲;
  • 過期文件會被自動清理。

對于微信之外的空間占用,例如相冊、視頻、其他App的空間占用,微信本身是做不了什么事情的,我們可以提示用戶進行空間清理:

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、SQLite 修復邏輯優化

3.1、master 表

首先我們來看 SQLite 的架構。SQLite 使用 B+樹 存儲一個表,整個 SQLite 數據庫就是這些 B+樹 組成的森林。對于每個表的元數據(表名、根節點地址、表 scheme 等),都記錄在一個叫 sql_master 的表中。這個 sql_master 表(下簡稱 master 表) 本身也是一個 B+樹 存儲的普通表。

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 表,我們成功將修復成功率提高了一倍多。

4、其他

通過這些優化,我們提高了微信聊天記錄存儲的可靠性。這些優化實踐,會同之前在并發性能方面的優化實踐(微信iOS SQLite源碼優化實踐),將會合并到微信即將開源的 WCDB(WeChat Database)組件中。我們正在進行緊張的代碼整理工作,爭取在 2017 年年中開源 WCDB。


更多精彩內容歡迎關注騰訊 Bugly的微信公眾賬號:

騰訊 Bugly是一款專為移動開發者打造的質量監控工具,幫助開發者快速,便捷的定位線上應用崩潰的情況以及解決方案。智能合并功能幫助開發同學把每天上報的數千條 Crash 根據根因合并分類,每日日報會列出影響用戶數最多的崩潰,精準定位功能幫助開發同學定位到出問題的代碼行,實時上報可以在發布后快速的了解應用的質量情況,適配最新的 iOS, Android 官方操作系統,鵝廠的工程師都在使用,快來加入我們吧!

轉載于:https://www.cnblogs.com/bugly/p/6824261.html

總結

以上是生活随笔為你收集整理的微信 SQLite 数据库修复实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。