H2數據庫中一條insert語句到生成java對象到數據寫入磁盤的完整步驟

H2 數據庫將 SQL 語句轉換為磁盤存儲的全過程可以分為以下 8 個關鍵步驟,我們以 INSERT INTO users (id, name) VALUES (1, 'Alice') 為例詳細說明:


1. SQL 解析與語法樹生成

  • 詞法分析:拆分語句為 INSERTINTOusers 等 Token
  • 語法分析:構建抽象語法樹(AST),驗證表結構是否存在
  • 語義分析:確認 idname 字段類型匹配

2. 事務管理與日志寫入(WAL)

– 隱式事務開始
INSERT INTO users VALUES (1, ‘Alice’);
– COMMIT 觸發日志落盤

  • 預寫日志:先將操作記錄寫入 .trace.db 文件

  • 日志格式

    INSERT INTO PUBLIC.USERS(ID, NAME) VALUES (1, ‘Alice’)


3. 內存數據結構操作

  • MVStore 引擎(默認):
    • 將數據暫存內存中的 B+Tree 結構

    • Key-Value 存儲格式:

      {
      “key”: 1,
      “value”: {
      “id”: 1,
      “name”: “Alice”
      }
      }


4. 頁式存儲管理(PageStore)


5. 索引維護

  • 主鍵索引:自動創建 PRIMARY_KEY_INDEX

    // B+Tree 結構示例
    BPlusTree index = new BPlusTree();
    index.put(1, new PagePointer(0x01, 128)); // 指向頁0x01的128字節偏移


6. 檢查點(Checkpoint)觸發

  • 觸發條件
    • 事務提交時設置 FORCE_WRITE=true
    • 內存中臟頁比例超過閾值(默認 50%)
  • 持久化過程
    1. 暫停新事務
    2. 將內存中的 B+Tree 序列化為二進制格式
    3. 追加寫入 .h2.db 文件

7. 物理存儲結構

數據庫文件結構

users.h2.db # 主數據文件
users.temp.db # 臨時文件(合并操作時使用)
users.lock.db # 文件鎖控制
users.trace.db # WAL 日志文件


8. 崩潰恢復機制

當異常關閉后重啟時:

  1. 檢查 .trace.db 日志文件
  2. 回放未提交的事務(Rollback)
  3. 驗證 .h2.db 文件的 checksum
  4. 重建內存中的 B+Tree 索引

技術亮點

  1. MVCC 實現:通過 TRANSACTION_ID 字段實現多版本控制
  2. 壓縮優化:使用 LZF 算法壓縮數據頁(默認關閉)
  3. 加密支持:可選 AES-128 加密整個數據文件

通過這種分層處理機制,H2 既保證了 ACID 特性,又能達到 50,000+ TPS 的寫入性能(內存模式)。實際存儲格式會根據 MVStorePageStore 引擎的選擇有所不同,以上流程以 MVStore 為主。


**user**: 

重新生成一遍,sql ,解析成java 對象,用了什么數據結構,索引,如何存儲到磁盤的


**assistant**: 

以下是 H2 數據庫將 SQL 語句轉換為 Java 對象并最終存儲到磁盤的完整技術過程,結合 INSERT INTO users (id, name) VALUES (1, 'Alice') 示例:


1. **SQL 解析與 Java 對象生成

解析過程

// 使用 H2 的解析器生成 Command 對象
Parser parser = new Parser(connection);
String sql = “INSERT INTO users (id, name) VALUES (1, ‘Alice’)”;
Command command = parser.parseCommand(sql); // 返回 Insert 對象

// Insert 對象結構 (org.h2.command.dml.Insert)
class Insert {
Table table; // users 表的元數據
Column[] columns; // [id, name]
Expression[] values; // [1, ‘Alice’]
int rowId; // 內存中的臨時行號
}

關鍵數據結構

// 內存中的行數據表示 (org.h2.result.Row)
Row row = table.getTemplateRow();
row.setValue(0, ValueInt.get(1)); // id 列
row.setValue(1, ValueString.get(“Alice”)); // name 列

// 值對象的內存結構 (org.h2.value.Value)
class ValueInt {
int value;
byte[] memoryBytes; // 序列化后的字節緩存(用于快速存儲)
}


2. **內存數據結構與索引

表數據存儲(MVStore 引擎)

// MVStore 的 B+Tree 實現 (org.h2.mvstore.MVMap)
MVMap<Integer, Row> tableMap = store.openMap(“users”);

// 插入數據到內存樹
tableMap.put(1, row); // key=id, value=Row對象

// Row 的內存結構
class Row {
Value[] data; // [1, “Alice”]
long version; // MVCC 版本號
int transactionId; // 關聯的事務ID
}

索引結構(B+Tree 實現)

// 主鍵索引 (org.h2.index.PageBtreeIndex)
PageBtreeIndex primaryIndex = new PageBtreeIndex(…);

// 索引節點結構
class BTreeNode {
Object[] keys; // [1]
long[] children; // 子節點頁號(內存地址或磁盤頁ID)
boolean isLeaf;
}

// 索引條目
class IndexEntry {
int key; // id=1
PagePointer pointer;// 指向數據頁的位置 (pageId=0x01, offset=128)
}


3. **磁盤存儲細節

MVStore 文件格式(默認引擎)

數據文件 users.mv.db 的二進制結構

[File Header] [Chunk 1] [Chunk 2] … [Chunk N]

Chunk 結構示例

Chunk {
int chunkId; // 遞增的塊ID
long blockCount; // 占用的塊數
byte[] mapData; // 序列化的 MVMap 數據
byte[] btreeNodes; // B+Tree 節點二進制數據
}

單行存儲的二進制格式

// Row 的序列化過程
ByteBuffer buf = ByteBuffer.allocate(128);
DataUtils.writeVarInt(buf, 1); // id
DataUtils.writeString(buf, “Alice”); // name
byte[] rowBytes = buf.array(); // 最終字節數組

// 磁盤存儲示例(十六進制):
01 00 00 00 // id=1 (4字節)
41 6C 69 63 65 // “Alice” (UTF-8 bytes)

頁式存儲(PageStore 引擎)

// 數據頁結構 (org.h2.store.Page)
class Page {
int pageId; // 0x01
byte[] data; // 頁內容(包含多行數據)
int type; // 頁類型(數據頁/索引頁)
}

// 頁內數據組織
DataPage {
Row[] rows; // 行數據數組
int freeSpace; // 剩余空間計數
int nextPage; // 下一頁指針
}


4. **持久化觸發機制

事務提交時的寫入

// 事務提交操作 (org.h2.engine.Session)
session.commit();

// 持久化步驟:

  1. 將 MVStore 的臟頁標記為待寫入
  2. 通過 FileStore.write() 異步寫入磁盤
  3. 更新文件頭部的元數據塊

// 關鍵寫入類
FileStore fileStore = new FileStore();
fileStore.write(ByteBuffer data, long position); // 直接操作文件通道

檢查點(Checkpoint)示例

// 檢查點線程 (org.h2.engine.CheckpointThread)
public void run() {
if (needCheckpoint()) {
store.sync(); // 強制同步內存數據到磁盤
}
}

// 觸發條件:
// - 超過 checkpointInterval (默認 30秒)
// - 日志文件超過 16MB


5. **技術關鍵點

  1. 內存與磁盤的橋梁

    • Row 對象同時存在于內存(Java Heap)和堆外內存(DirectByteBuffer)
    • 通過 Value#getBytes() 實現快速序列化
  2. 索引加速

    // 索引查詢示例
    Cursor cursor = primaryIndex.find(1); // 二分查找 B+Tree
    Page page = readPage(cursor.getPageId());
    Row row = page.getRow(cursor.getOffset());

  3. 壓縮與加密

    // 文件存儲配置
    MVStore.Builder()
    .compress() // 啟用 LZF 壓縮
    .encryptionKey(“AES”, “password”.toCharArray());


完整流程示例

  1. 用戶發送 INSERT SQL
  2. 生成 Insert 命令對象
  3. 創建 Row 并填充 Value 數據
  4. 更新內存中的 MVMap(B+Tree)
  5. 事務提交時觸發:
    • 寫入 WAL 日志(.trace.db
    • 標記臟頁
    • 異步線程執行磁盤寫入
  6. 數據最終以分塊形式持久化到 .mv.db 文件

通過這種設計,H2 在保證 ACID 的同時,內存模式可達 50,000 TPS,持久化模式性能約為 8,000 TPS(取決于磁盤速度)。開發者可通過 MVStore API 直接操作底層存儲結構。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/81901.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/81901.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/81901.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

重磅升級!Google Play商店改版上線

5 月 21 日消息&#xff0c;Android Headline 今天&#xff08;5 月 21 日&#xff09;發布博文&#xff0c;報道稱在 2025 年 I/O 開發者大會上&#xff0c;谷歌宣布更新 Google Play 應用商店&#xff0c;在優化用戶體驗的同時&#xff0c;提升開發者收益。 本次更新中&…

Docker面試題(1)

什么是Docker 一個容器化平臺 形式是容器 將你的應用程序及所有依賴項打包在一起 確保應用程序在任何環境中無縫運行 什么是Docker鏡像 Docker鏡像是Docker容器的源代碼 用于創建容器 使用build命令創建鏡像 什么是 Docker容器 包括應用程序及所有的依賴項 作為操作系統的獨立進…

Ulisses Braga-Neto《模式識別和機器學習基礎》

模式識別和機器學習基礎 [專著] Fundamentals of pattern recognition and machine learning / (美)烏利塞斯布拉加&#xff0d;內托(Ulisses Braga-Neto)著 ; 潘巍[等]譯 推薦這本書&#xff0c;作者有自己的見解&#xff0c;而且提供代碼。問題是難度高&#xff0c;對于初學…

RabbitMQ的簡介

三個概念 生產者&#xff1a;生產消息的服務消息代理&#xff1a;消息中間件&#xff0c;如RabbitMQ消費者&#xff1a;獲取使用消息的服務 消息隊列到達消費者的兩種形式 隊列&#xff08;queue&#xff09;:點對點消息通信&#xff08;point-to-point&#xff09; 消息進入隊…

自動切換剪貼板路徑中反斜杠為正斜杠

有時候需要將我們常見的win全路徑中反斜杠為正斜杠&#xff0c;每次用記事本&#xff0c;編輯替換非常麻煩&#xff0c;于是寫了這個工具&#xff0c;能自動修改剪貼板中的數據&#xff0c;只需要運行一下即可。 實現效果&#xff0c;將類似于下面的路徑&#xff1a; C:\User…

【時時三省】Python 語言----文件

目錄 1,文件打開 2, 文件關閉 3, 文件寫入 4, 文件讀出 5, 文件定位 6, 文件重命名 7, 復制文件 山不在高,有仙則名。水不在深,有龍則靈。 ----CSDN 時時三省 1,文件打開 file = open(file, mode, buffering, encoding, errors, newline, closefd, opener) 2, 文…

React 個人筆記 Hooks編程

作用 配合函數式編程&#xff0c;保證在不產生類的時候完成一個整體的組件 常用組件 useStateuseContextuseReduceruseEffectuseMemouseCallback 前三個值為自變量 后三者為因變量 前三者相當于其他編程函數的變量聲明&#xff0c;而后三者相當于對變量進行了(if now ! pr…

logits是啥、傅里葉變換

什么是logtis&#xff1f; 在深度學習的上下文中&#xff0c;logits 就是一個向量&#xff0c;下一步通常被投給 softmax/sigmoid 的向量。。 softmax的輸出是分類任務的概率&#xff0c;其輸入是logits層。 logits層通常產生-infinity到 infinity的值&#xff0c;而softmax層…

Adobe Illustrator學習備忘

1.移動畫板&#xff1a;需按住空格鍵加鼠標一塊才能拖動 2.放大縮小畫板&#xff1a;按住Alt鍵加鼠標滾輪 3.撤回&#xff1a;CtrlZ 4.鋼筆練習網站&#xff1a;The Bzier Game

【初識】內網滲透——基礎概念,基本工具使用

目錄 一、域&#xff0c;工作組&#xff0c;域控制器&#xff0c;活動目錄相關概念&#xff1a; 域環境&#xff1a; 工作組&#xff1a; 域控制器DC&#xff1a; 活動目錄AD&#xff1a; 二、內網的基本場景&#xff1a; 三、內網滲透基本測試方案&#xff1a; #案例1一基本信…

remove_const的工作原理及c++的類型推導

author: hjjdebug date: 2025年 05月 21日 星期三 12:51:57 CST descrip: remove_const的工作原理及c的類型推導 文章目錄 1. 簡單的程序代碼.2.std::remove_const_t 到底是怎樣工作的&#xff1f;2.1 測試代碼2.2 類型推導的調試手段.2.2.1 給類模板添加成員函數,讓它打印信息…

人臉識別,使用 deepface + api + flask, 改寫 + 調試

1. 起因&#xff0c; 目的&#xff0c; 感受: github deepface 這個項目寫的很好&#xff0c; 繼續研究使用這個項目&#xff0c;改寫 api。增加一個前端 flask app 2. 先看效果 3. 過程: 大力改寫原始項目中 api 這部分的代碼&#xff0c; 原始項目的文件結構太繁雜了: 我把…

三維表面輪廓儀的維護保養是確保其長期穩定運行的關鍵

三維表面輪廓儀是一種高精度測量設備&#xff0c;用于非接觸式或接觸式測量物體表面的三維形貌、粗糙度、臺階高度、紋理特征等參數。其主要基于光學原理進行測量。它利用激光或其他光源投射到被測物體表面&#xff0c;通過接收反射光或散射光&#xff0c;結合計算機圖像處理技…

Lambda表達式的高級用法

今天來分享下Java的Lambda表達式&#xff0c;以及它的高級用法。 使用它可以提高代碼的簡潔度&#xff0c;使代碼更優雅。 一、什么是lambda表達式 Lambda 表達式是 Java 8 引入的特性&#xff0c;用于簡化匿名內部類的語法&#xff0c;使代碼更簡潔&#xff0c;尤其在處理函…

31-35【動手學深度學習】深度學習硬件

1. CPU和GPU 1.1 CPU CPU每秒鐘計算的浮點運算數為0.15&#xff0c;GPU為12。GPU的顯存很低&#xff0c;16GB&#xff08;可能32G封頂&#xff09;&#xff0c;CPU可以一直插內存。 左邊是GPU&#xff08;只能做些很簡單的游戲&#xff0c;視頻處理&#xff09;&#xff0c;中…

【MySQL成神之路】MySQL常見命令匯總

目錄 MySQL常用命令總結 1. 數據庫操作 2. 表操作 3. 數據操作&#xff08;DML&#xff09; 4. 索引與優化 5. 用戶與權限管理 6. 備份與恢復 7. 事務控制 8. 常用函數 9. 系統狀態與日志 總結 MySQL常用命令總結 MySQL作為最流行的關系型數據庫之一&#xff0c;提供…

Dify的大語言模型(LLM) AI 應用開發平臺-本地部署

前言 今天閑著&#xff0c;搗鼓一下 Dify 這個開源平臺&#xff0c;在 mac 系統上&#xff0c;本地部署并運行 Dify 平臺&#xff0c;下面記錄個人在本地部署Dify 的過程。 Dify是什么&#xff1f; Dify是一個開源的大語言模型&#xff08;LLM&#xff09;應用開發平臺&#…

【論文閱讀】針對BEV感知的攻擊

Understanding the Robustness of 3D Object Detection with Bird’s-Eye-View Representations in Autonomous Driving 這篇文章是發表在CVPR上的一篇文章&#xff0c;針對基于BEV的目標檢測算法進行了兩類可靠性分析&#xff0c;即惡劣自然條件以及敵對攻擊。同時也提出了一…

SonarQube的核心作用與用途

SonarQube作為一個開源的代碼質量管理平臺&#xff0c;致力于持續分析代碼的健康狀態&#xff0c;幫助開發團隊提升代碼質量。以下是其核心作用與用途的詳細說明&#xff1a; 1、靜態代碼分析 SonarQube通過靜態代碼分析技術&#xff0c;自動識別代碼中的潛在問題。它能夠檢測…

AI工程師系列——面向copilot編程

前言 ? 筆者已經使用copilot協助開發有一段時間了,但一直沒有總結一個協助代碼開發的案例,特別是怎么問copilot,按照什么順序問,哪些方面可以高效的生成需要的代碼,這一次,筆者以IP解析需求為例,沉淀一個實踐案例,供大家參考 當然,其實也不局限于copilot本身,類似…