文章目錄
簡介: USTC計算機院高級數據庫課程實驗1 - 實現Storage and Buffer Manager. 源代碼在我的Github上advance_db_exp1,歡迎star(issue)。
功能需求描述
數據管理模塊 DataStorageManager
提供記錄的增改查操作,作爲DBMS的底層模塊,爲上層緩衝區管理模塊提供接口。
- 下層: 調用操作系統提供的文件系統,實現目錄式的記錄管理
- 上層: 提供讀取讀取/更新某個頁,寫入新頁等功能
- 外部接口
- 初始化相關文件信息
- 讀取page
- 寫入新page
- 更新page
- 獲取頁數、IO總數
- 內部接口
- 打開、關閉文件
- 讀取、更新目錄
- 讀取某個目錄
- 實現方式優缺點
- 優點: 擴展性更好,可以存儲變長記錄
- 缺點: 讀取目錄會增加IO次數,實現更復雜
- 權衡: 重用內存內部的目錄,不需要每次從0號目錄開始讀取
緩衝區管理 BufferManager
提供基於LRU的緩存管理功能,提高記錄讀取/更新的效率。爲上層SQL執行模塊提供接口,下層調用數據管理模塊的接口執行數據更新。
- 上層爲記錄查詢提供增刪改查功能
- 下層調用數據管理接口的功能
- 外部接口
- 讀取某個page內容
- 更新某個page內容
- 增加一個新page
- 獲取某個frame
- 獲取命中率
- 獲取IO總數
- 獲取LRU頭、尾信息
- 將所有髒頁寫入磁盤
- 獲取可用frame數目
- 內部接口
- 根據淘汰算法選擇受害者
- 設置/取消設置一個頁爲髒頁
- 將所有髒頁寫入磁盤
- 打印一個frame的內容
- 根據LRU算法更新一個緩衝塊
- 根據LRU算法插入一個新的緩衝塊
數據結構設計
DataStorageManager
頁大小爲8KB,使用一頁作爲目錄,存儲N=(8*1024/4)=2*1024
個頁地址和下一個目錄表的地址。其中頁地址與目錄表地址爲偏移量,使用長整數(4Byte)表示。目錄表信息用於重用目錄。
- 文件指針: FILE* fp
- 頁數: numpages
- 目錄表: contents -> int[], 在堆上分配
- 目錄表信息: 目錄的偏移量與序號
- 當前目錄在文件中的偏移量: cur_content_offset
- 當前目錄的序號: cur_content_id
BufferManager
- 緩衝區: buffer[]
- 緩衝區大小: size
- 鏈表首/尾: head_frame_id, tail_frame_id
- frame->page: frame2page[] 數組
- page->frame: page2frame[] 哈希表
- 緩衝塊信息(鏈表節點): bcb[] -> { frame_id, page_id, dirty, count, prev_frame_id, next_frame_id }
- 鏈表結構與哈希表結合使用,使用緩衝塊信息保存
運行結果
每次執行fread
或fwrite
時增加一次IO,總IO數爲1383506,IO曲線與命中率曲線如下:
問題與解決
-
fread莫名遇到eof,fseek、ftell都沒問題: 打開文件時指定
b
,即以二進制方式打開,如下爲fseek
相關信息For streams open in binary mode, the new position is defined by adding offset to a reference position specified by origin. For streams open in text mode, offset shall either be zero or a value returned by a previous call to ftell, and origin shall necessarily be SEEK_SET.
-
目錄讀取IO過多: 重用內存中的目錄
-
vscode莫名拋出 無法打開…cygwin.s: 由於棧內數組開的過大,造成了調試器啓動失敗!!!
-
文件太大,偏移量無法使用int存下?: 並不是文件太大,int作偏移量時文件理論最大值爲2GB,所以是因爲輸入數據中有不正常的數據(50000).另外gcc的 -D_FILE_OFFSET_BITS=64 能夠將off_t定義爲64位的,因此使用
off_t
作爲偏移量的類型之後使用該選項編譯運行即可