小文件分析 - (一)

主要參考:

  • 1惹谐、《SQLite數(shù)據(jù)庫文件格式全面分析.doc 》碾篡,鏈接不詳,只是能再網(wǎng)上各個文庫上找到此文檔蹂喻。
  • 2延赌、官網(wǎng)文檔 Database File Format

前提準(zhǔn)備

準(zhǔn)備好文件

在win10環(huán)境下

PS G:\code-2\sqlite3> ./sqlite3 small.db
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> CREATE TABLE department(id int, dept char(30), emp_id int);
sqlite> insert into department values(1, "test", -1);
sqlite> insert into department values(2, "test", 1);
sqlite> .qu

準(zhǔn)備一些小工具

從sqlite官網(wǎng)下載的源碼中的tool目錄中有一些十分有用的小工具,例如showdb叉橱、showwal等挫以,它們都是單個源文件組成,結(jié)合官網(wǎng)提供的sqlite-amalgamation-xxx.zip提供的sqlite3.hsqlite3.c就可以編譯出來窃祝。例如showdb是由showdb.c編譯出來的:gcc -g -O0 -o showdb showdb.c sqlite3.c掐松,調(diào)試和編譯優(yōu)化選項看個人喜歡,可加可不加粪小。

最最基礎(chǔ)的概念

首先要明白三點:

  • sqlite3數(shù)據(jù)庫是由單個文件組成的大磺,而這個文件被稱為主數(shù)據(jù)庫文件main database file。這個文件又是由多個頁page組成探膊,頁按順序編號杠愧,從1開始。sqlite上層的b樹最小組成單位就是頁逞壁,至于如何存儲流济,如何查找等我寫完就差不多弄清楚了锐锣。還有頁的分類都是后話,所有底層設(shè)計都是為了上層服務(wù)的绳瘟,個人理解的時候要會把握關(guān)鍵的思路雕憔,再慢慢理順細(xì)節(jié)。
  • 存儲在文件中的數(shù)據(jù)格式全部都是大端格式糖声,為什么是大端呢斤彼?不清楚,就像網(wǎng)絡(luò)字節(jié)序也是用大端存儲蘸泻,不過大端存儲在調(diào)式的時候有個明顯的優(yōu)勢就是符合人類閱讀習(xí)慣琉苇。
  • sqlite_schema 是一個特殊的表(別名有很多,例如sqlite_master)悦施,它存放著其余表對應(yīng)所在的根頁號翁潘,具體定義如下:
CREATE TABLE sqlite_schema(
  type text,
  name text,
  tbl_name text,
  rootpage integer,
  sql text
);

開始分析這個小文件

文件頭

主數(shù)據(jù)庫文件的前100個字節(jié)即是文件頭。格式官網(wǎng)也給出了:

Offset Size Description
0 16 The header string: "SQLite format 3\000"
16 2 The database page size in bytes. Must be a power of two between 512 and 32768 inclusive, or the value 1 representing a page size of 65536.
18 1 File format write version. 1 for legacy; 2 for WAL.
19 1 File format read version. 1 for legacy; 2 for WAL.
20 1 Bytes of unused "reserved" space at the end of each page. Usually 0.
21 1 Maximum embedded payload fraction. Must be 64.
22 1 Minimum embedded payload fraction. Must be 32.
23 1 Leaf payload fraction. Must be 32.
24 4 File change counter.
28 4 Size of the database file in pages. The "in-header database size".
32 4 Page number of the first freelist trunk page.
36 4 Total number of freelist pages.
40 4 The schema cookie.
44 4 The schema format number. Supported schema formats are 1, 2, 3, and 4.
48 4 Default page cache size.
52 4 The page number of the largest root b-tree page when in auto-vacuum or incremental-vacuum modes, or zero otherwise.
56 4 The database text encoding. A value of 1 means UTF-8. A value of 2 means UTF-16le. A value of 3 means UTF-16be.
60 4 The "user version" as read and set by the user_version pragma.
64 4 True (non-zero) for incremental-vacuum mode. False (zero) otherwise.
68 4 The "Application ID" set by PRAGMA application_id.
72 20 Reserved for expansion. Must be zero.
92 4 The version-valid-for number.
96 4 SQLITE_VERSION_NUMBER

對應(yīng)的小文件分析可以用showdb可知:

PS G:\code-2\sqlite3> ./showdb small.db dbheader
Pagesize: 4096
Available pages: 1..2
 000: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
 010: 10 00 01 01 00 40 20 20 00 00 00 03 00 00 00 02 .....@  ........
 020: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
 030: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
 040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
 050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 ................
 060: 00 2e 34 20 00                                  ..4 .
Decoded:
 010: 10 00              4096  Database page size
 012: 01                    1  File format write version
 013: 01                    1  File format read version
 014: 00                    0  Reserved space at end of page
 018: 00 00 00 03           3  File change counter
 01c: 00 00 00 02           2  Size of database in pages
 020: 00 00 00 00           0  Page number of first freelist page
 024: 00 00 00 00           0  Number of freelist pages
 028: 00 00 00 01           1  Schema cookie
 02c: 00 00 00 04           4  Schema format version
 030: 00 00 00 00           0  Default page cache size
 034: 00 00 00 00           0  Largest auto-vac root page
 038: 00 00 00 01           1  Text encoding
 03c: 00 00 00 00           0  User version
 040: 00 00 00 00           0  Incremental-vacuum mode
 044: 00 00 00 00           0  Application ID
 048: 00 00 00 00           0  meta[8]
 04c: 00 00 00 00           0  meta[9]
 050: 00 00 00 00           0  meta[10]
 054: 00 00 00 00           0  meta[11]
 058: 00 00 00 00           0  meta[12]
 05c: 00 00 00 03           3  Change counter for version number
 060: 00 2e 34 20     3028000  SQLite version number

頁大小 (Database page size)

在0x10偏移處歼争,規(guī)定了頁的大小,取值必須是2的冪次方渗勘,范圍為[512, 65536]沐绒,這里有點小細(xì)節(jié)可以參考官網(wǎng)文檔可知。

文件格式版本(File format write/read version)

現(xiàn)在僅存在1和2兩種旺坠,分別代表Hot journalWAL journal乔遮。小文件分析時候采用的是前者。

頁的保留空間大小 (Reserved space at end of page)

保留空間是在頁的尾部開始取刃,其的用途例如在加密插件啟用的時候蹋肮,存儲nonce值或者頁面的校驗和。一般來說這個字段一般為0璧疗。

Payload Fraction

0x21-23是連續(xù)的頁內(nèi)每個單元占用的百分比坯辩,以255為分母,這三個值64\32\32分別做分子崩侠,可得到對應(yīng)的百分比25%漆魔,12.5%,12.5%却音。前兩個是給index使用的改抡,分別表示最大和最小值,后一個是給table b-tree leaf page的最小值系瓢,其最大值是是pagesize - 35

文件修改次數(shù)計數(shù)器(File change counter)

統(tǒng)計每一次修改數(shù)據(jù)庫文件阿纤,到目前為止,我們先是創(chuàng)建表一次夷陋,兩次獨立(相當(dāng)于兩次事務(wù))的插入操作欠拾,所以總共修改了文件3次胰锌。

當(dāng)前數(shù)據(jù)庫頁的數(shù)目(Size of database in pages)

字面意思,不過歷史版本上對其處理還是有不一樣的清蚀,這個值會需要進(jìn)一步的和數(shù)據(jù)庫文件大小相比較匕荸,如果不一致則采用具體的數(shù)據(jù)庫文件大小。

空閑頁

這里開始涉及到頁的分類了枷邪,先簡單的理解一下空閑頁榛搔。它的存在是因為數(shù)據(jù)庫在進(jìn)行刪除操作的時候,導(dǎo)致整一頁的數(shù)據(jù)都被清除掉了东揣,此時就要把該頁添加入空閑頁鏈表践惑。
這個鏈表在文件中的存儲方式,是隱式鏈表嘶卧,也就是頁頭會存放著指向下一個空閑頁的下標(biāo)尔觉。而第一個空閑頁則由主數(shù)據(jù)庫文件的文件頭給出。
回到我們的小文件分析芥吟,此時我們的數(shù)據(jù)庫沒有多余的頁侦铜,所以Page number of first freelist page == 0,0可以理解為c語言中的NULL钟鸵,并且空閑頁數(shù)目也等于0

Schema cookie

這里的Schema钉稍,中文翻譯怎么都不太恰當(dāng)。它是整個數(shù)據(jù)庫所有表的總和棺耍,而這cookie則是一個整數(shù)贡未,每次Schema發(fā)生改動(也就是發(fā)生表的增刪改操作)就自增。這里一個相關(guān)的使用場景就是調(diào)用sqlite3_step的時候會去檢查schema是否發(fā)生變化蒙袍。

Schema format number

它代表著schema不同歷史時期的功能支持程度俊卤,可以見官網(wǎng)描述。這里直接摘抄原文害幅,現(xiàn)在默認(rèn)是用版本4消恍。

    1. Format 1 is understood by all versions of SQLite back to version 3.0.0 (2004-06-18).
    1. Format 2 adds the ability of rows within the same table to have a varying number of columns, in order to support the ALTER TABLE ... ADD COLUMN functionality. Support for reading and writing format 2 was added in SQLite version 3.1.3 on 2005-02-20.
    1. Format 3 adds the ability of extra columns added by ALTER TABLE ... ADD COLUMN to have non-NULL default values. This capability was added in SQLite version 3.1.4 on 2005-03-11.
    1. Format 4 causes SQLite to respect the DESC keyword on index declarations. (The DESC keyword is ignored in indexes for formats 1, 2, and 3.) Format 4 also adds two new boolean record type values (serial types 8 and 9). Support for format 4 was added in SQLite 3.3.0 on 2006-01-10.

Default page cache size

默認(rèn)的頁緩存大小,只是一個建議以现,實際上由程序自己判斷

Incremental vacuum settings

Largest auto-vac root pageIncremental-vacuum mode 都是vacuum相關(guān)的設(shè)置哺哼,前者是auto_vacuum模式使用,后者是incremental_vacuum模式使用叼风。當(dāng)前者等于0時候取董,ptrmap類型的頁將會被從數(shù)據(jù)庫文件中剔除,并且這兩種模式都不會被支持无宿。當(dāng)前者不為0的時候茵汰,它指向的是最大的根頁,儲存著許多ptrmap類型的頁孽鸡,并且此時由后者控制是auto_vacuum還是incremental_vacuum

文本編碼 Text encoding

  • 1 for UTF-8
  • 2 for UTF16LE
  • 3 for UTF16BE

User version

這是給用戶使用的版本號蹂午,sqlite3 并不使用它栏豺。這好像在系統(tǒng)升級的時候確實有用

Application ID

這個也是留給用戶使用的,表示當(dāng)前是由那個進(jìn)程在使用豆胸。這個用處沒這么大奥洼。

sqlite3 庫使用的版本

Change counter for version numberSQLite version number,在0x5c和0x60存放的是sqlite3.so/sqlite3.dll在使用此數(shù)據(jù)庫文件時候晚胡,存放的版本號灵奖,并且自增修改次數(shù)。用途不太明確估盘,但是應(yīng)該用來判斷是否有不同版本的sqlite3庫修改此文件吧瓷患。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市遣妥,隨后出現(xiàn)的幾起案子擅编,更是在濱河造成了極大的恐慌,老刑警劉巖箫踩,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爱态,死亡現(xiàn)場離奇詭異,居然都是意外死亡境钟,警方通過查閱死者的電腦和手機(jī)锦担,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吱韭,“玉大人,你說我怎么就攤上這事鱼的±砼瑁” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵凑阶,是天一觀的道長猿规。 經(jīng)常有香客問我,道長宙橱,這世上最難降的妖魔是什么姨俩? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮师郑,結(jié)果婚禮上环葵,老公的妹妹穿的比我還像新娘。我一直安慰自己宝冕,他們只是感情好张遭,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著地梨,像睡著了一般菊卷。 火紅的嫁衣襯著肌膚如雪缔恳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天洁闰,我揣著相機(jī)與錄音歉甚,去河邊找鬼。 笑死扑眉,一個胖子當(dāng)著我的面吹牛纸泄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播襟雷,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼刃滓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了耸弄?” 一聲冷哼從身側(cè)響起咧虎,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎计呈,沒想到半個月后砰诵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡捌显,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年茁彭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扶歪。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡理肺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出善镰,到底是詐尸還是另有隱情妹萨,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布炫欺,位于F島的核電站乎完,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏品洛。R本人自食惡果不足惜树姨,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桥状。 院中可真熱鬧帽揪,春花似錦、人聲如沸辅斟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挽霉,卻和暖如春防嗡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背侠坎。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工蚁趁, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人实胸。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓他嫡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庐完。 傳聞我的和親對象是個殘疾皇子钢属,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 頁 主數(shù)據(jù)庫文件頭之后的都是頁的內(nèi)容了,頁的分類主要有5種:b-tree 頁门躯,overflow 頁淆党,free 頁,...
    5dplay閱讀 269評論 0 0
  • 隨著app信息量越來越大讶凉,每次從網(wǎng)絡(luò)獲取數(shù)據(jù)已經(jīng)不是很可取的方案了染乌,本地數(shù)據(jù)庫的運用已經(jīng)越來越普遍了。而說道移動端...
    taosiyu閱讀 4,621評論 12 13
  • 原文PRAGMA語句是SQLITE數(shù)據(jù)的SQL擴(kuò)展懂讯,是它獨有的特性荷憋,主要用于修改SQLITE庫或者內(nèi)數(shù)據(jù)查詢的操作...
    _小沫閱讀 1,358評論 0 1
  • SQLite 的 PRAGMA 命令是一個特殊的命令,可以用在 SQLite 環(huán)境內(nèi)控制各種環(huán)境變量和狀態(tài)標(biāo)志褐望。一...
    元茜姑娘閱讀 925評論 0 7
  • WCDB簡介 WCDB(wechat dataBase)是一個高效勒庄、完整、易用的開源移動數(shù)據(jù)庫框架瘫里,基于SQLCi...
    Shmily魚閱讀 13,362評論 0 2