未验证 提交 fe061d05 编写于 作者: 羽飞's avatar 羽飞 提交者: GitHub

Document (#197)

### What problem were solved in this pull request?

Problem:
当前生成的github pages不太整洁方便,可以优化一下

### What is changed and how it works?
改用mdbook生成文档,并整理文档目录,调整链接
上级 93b79cc6
# Sample workflow for building and deploying a Jekyll site to GitHub Pages # Sample workflow for building and deploying a mdBook site to GitHub Pages
name: Deploy Jekyll with GitHub Pages dependencies preinstalled #
# To get started with mdBook see: https://rust-lang.github.io/mdBook/index.html
#
name: Deploy mdBook site to Pages
on: on:
# Runs on pushes targeting the default branch # Runs on pushes targeting the default branch
...@@ -25,11 +28,23 @@ jobs: ...@@ -25,11 +28,23 @@ jobs:
# Build job # Build job
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
MDBOOK_VERSION: 0.4.21
steps: steps:
- name: Checkout - uses: actions/checkout@v3
uses: actions/checkout@v3 - name: Install mdBook
with: run: |
submodules: false curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf -y | sh
rustup update
cargo install --version ${MDBOOK_VERSION} mdbook
- name: Setup Pages
id: pages
uses: actions/configure-pages@v3
- name: Build with mdBook
run: mdbook build
working-directory: ./docs
- name: Doxygen Action - name: Doxygen Action
uses: mattnotmitt/doxygen-action@v1.9.5 uses: mattnotmitt/doxygen-action@v1.9.5
...@@ -37,17 +52,10 @@ jobs: ...@@ -37,17 +52,10 @@ jobs:
working-directory: . working-directory: .
doxyfile-path: ./Doxyfile doxyfile-path: ./Doxyfile
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Build with Jekyll
uses: actions/jekyll-build-pages@v1
with:
source: ./
destination: ./_site
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@v1 uses: actions/upload-pages-artifact@v1
with:
path: docs/book
# Deployment job # Deployment job
deploy: deploy:
......
...@@ -22,4 +22,5 @@ compile_commands.json ...@@ -22,4 +22,5 @@ compile_commands.json
GRTAGS GRTAGS
GPATH GPATH
GTAGS GTAGS
docs/book
#*# #*#
...@@ -6,17 +6,17 @@ OceanBase 社区热情欢迎每一位对数据库技术热爱的开发者,期 ...@@ -6,17 +6,17 @@ OceanBase 社区热情欢迎每一位对数据库技术热爱的开发者,期
为了帮助开发者更好的上手并学习 miniob, 建议阅读: 为了帮助开发者更好的上手并学习 miniob, 建议阅读:
1. [miniob 框架介绍](https://github.com/oceanbase/miniob/blob/main/docs/miniob-introduction.md) 1. [miniob 框架介绍](docs/src/miniob-introduction.md)
2. [如何编译 miniob 源码](https://github.com/oceanbase/miniob/blob/main/docs/how_to_build.md) 2. [如何编译 miniob 源码](docs/src/how_to_build.md)
3. [开发环境搭建(本地调试, 适用 Linux 和 Mac)](https://github.com/oceanbase/miniob/blob/main/docs/how_to_dev_miniob_by_vscode.md) 3. [开发环境搭建(本地调试, 适用 Linux 和 Mac)](docs/src/dev-env/how_to_dev_miniob_by_vscode.md)
4. [开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)](https://github.com/oceanbase/miniob/blob/main/docs/how_to_dev_in_docker_container_by_vscode.md) 4. [开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)](docs/src/dev-env/how_to_dev_in_docker_container_by_vscode.md)
5. [miniob 词法语法解析开发与测试](docs/miniob-sql-parser.md) 5. [miniob 文档汇总](docs/src/SUMMARY.md)
更多的文档, 可以参考 [docs](https://github.com/oceanbase/miniob/tree/main/docs), 为了帮助大家更好的学习数据库基础知识, OceanBase 社区提供了一系列教程, 建议学习: 更多的文档, 可以参考 [docs](https://github.com/oceanbase/miniob/tree/main/docs), 为了帮助大家更好的学习数据库基础知识, OceanBase 社区提供了一系列教程, 建议学习:
1. [《从0到1数据库内核实战教程》 视频教程](https://open.oceanbase.com/activities/4921877?id=4921946) 1. [《从0到1数据库内核实战教程》 视频教程](https://open.oceanbase.com/activities/4921877?id=4921946)
2. [《从0到1数据库内核实战教程》 基础讲义](https://github.com/oceanbase/kernel-quickstart) 2. [《从0到1数据库内核实战教程》 基础讲义](https://github.com/oceanbase/kernel-quickstart)
3. [《数据库管理系统实现》 华中科技大学实现教材](https://github.com/oceanbase/miniob/blob/main/docs/lectures/index.md) 3. [《数据库管理系统实现》 华中科技大学实现教材](docs/src/lectures/index.md)
## 如何找到一个合适issue ## 如何找到一个合适issue
......
...@@ -68,7 +68,7 @@ PROJECT_LOGO = ...@@ -68,7 +68,7 @@ PROJECT_LOGO =
# entered, it will be relative to the location where doxygen was started. If # entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used. # left blank the current directory will be used.
OUTPUT_DIRECTORY = docs/doxy OUTPUT_DIRECTORY = docs/book/design/doxy
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
# sub-directories (in 2 levels) under the output directory of each output format # sub-directories (in 2 levels) under the output directory of each output format
...@@ -120,7 +120,7 @@ OUTPUT_LANGUAGE = Chinese ...@@ -120,7 +120,7 @@ OUTPUT_LANGUAGE = Chinese
# documentation (similar to Javadoc). Set to NO to disable this. # documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES. # The default value is: YES.
BRIEF_MEMBER_DESC = NO BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description # description of a member or function before the detailed description
...@@ -524,13 +524,13 @@ EXTRACT_ALL = NO ...@@ -524,13 +524,13 @@ EXTRACT_ALL = NO
# be included in the documentation. # be included in the documentation.
# The default value is: NO. # The default value is: NO.
EXTRACT_PRIVATE = NO EXTRACT_PRIVATE = YES
# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual # If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
# methods of a class will be included in the documentation. # methods of a class will be included in the documentation.
# The default value is: NO. # The default value is: NO.
EXTRACT_PRIV_VIRTUAL = NO EXTRACT_PRIV_VIRTUAL = YES
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation. # scope will be included in the documentation.
...@@ -542,7 +542,7 @@ EXTRACT_PACKAGE = NO ...@@ -542,7 +542,7 @@ EXTRACT_PACKAGE = NO
# included in the documentation. # included in the documentation.
# The default value is: NO. # The default value is: NO.
EXTRACT_STATIC = NO EXTRACT_STATIC = YES
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO, # locally in source files will be included in the documentation. If set to NO,
......
# miniob 概述 # MiniOB 概述
miniob[OceanBase](https://github.com/oceanbase/oceanbase) 与华中科技大学联合开发的、面向"零"基础同学的数据库入门学习项目。 MiniOB[OceanBase](https://github.com/oceanbase/oceanbase) 与华中科技大学联合开发的、面向"零"基础同学的数据库入门学习项目。
miniob 设计的目标是面向在校学生、数据库从业者、爱好者,或者对基础技术有兴趣的爱好者, 整体代码量少,易于上手并学习, 是一个系统性的数据库学习项目。miniob 设置了一系列由浅入深的题目,以帮助同学们"零"基础入门, 让同学们快速了解数据库并深入学习数据库内核,期望通过相关训练之后,能够熟练掌握数据库内核模块的功能与协同关系, 并能够在使用数据库时,设计出高效的 SQL 。miniob 为了更好的学习数据库实现原理, 对诸多模块都做了简化,比如不考虑并发操作, 安全特性, 复杂的事物管理等功能。 MiniOB 设计的目标是面向在校学生、数据库从业者、爱好者,或者对基础技术有兴趣的爱好者, 整体代码量少,易于上手并学习, 是一个系统性的数据库学习项目。miniob 设置了一系列由浅入深的题目,以帮助同学们"零"基础入门, 让同学们快速了解数据库并深入学习数据库内核,期望通过相关训练之后,能够熟练掌握数据库内核模块的功能与协同关系, 并能够在使用数据库时,设计出高效的 SQL 。miniob 为了更好的学习数据库实现原理, 对诸多模块都做了简化,比如不考虑并发操作, 安全特性, 复杂的事物管理等功能。
(注意:此代码仅供学习使用,请勿用于生产项目。)
## 快速上手 ## 快速上手
为了帮助开发者更好的上手并学习 miniob, 建议阅读: 为了帮助开发者更好的上手并学习 miniob, 建议阅读:
1. [miniob 框架介绍](docs/miniob-introduction.md) 1. [miniob 框架介绍](docs/miniob-introduction.md)
2. [如何编译 miniob 源码](docs/how_to_build.md) 2. [如何编译 MiniOB 源码](docs/how_to_build.md)
3. [使用 GitPod 开发 MiniOB](docs/dev_by_gitpod.md) 3. [使用 GitPod 开发 MiniOB](docs/dev_by_gitpod.md)
4. [开发环境搭建(本地调试, 适用 Linux 和 Mac)](docs/how_to_dev_miniob_by_vscode.md) 4. [开发环境搭建(本地调试, 适用 Linux 和 Mac)](docs/how_to_dev_miniob_by_vscode.md)
5. [开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)](docs/how_to_dev_in_docker_container_by_vscode.md) 5. [开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)](docs/how_to_dev_in_docker_container_by_vscode.md)
6. [miniob 词法语法解析开发与测试](docs/miniob-sql-parser.md) 6. [MiniOB 词法语法解析开发与测试](docs/miniob-sql-parser.md)
7. [doxygen 代码文档](docs/doxy/html/index.html) 7. [doxygen 代码文档](docs/doxy/html/index.html)
或者直接看 [MiniOB GitHub Pages](https://oceanbase.github.io/miniob/).
更多的文档, 可以参考 docs 目录下的文档, 为了帮助大家更好的学习数据库基础知识, OceanBase 社区提供了一系列教程, 建议学习: 更多的文档, 可以参考 docs 目录下的文档, 为了帮助大家更好的学习数据库基础知识, OceanBase 社区提供了一系列教程, 建议学习:
1. [《从0到1数据库内核实战教程》 视频教程](https://open.oceanbase.com/activities/4921877?id=4921946) 1. [《从0到1数据库内核实战教程》 视频教程](https://open.oceanbase.com/activities/4921877?id=4921946)
2. [《从0到1数据库内核实战教程》 基础讲义](https://github.com/oceanbase/kernel-quickstart) 2. [《从0到1数据库内核实战教程》 基础讲义](https://github.com/oceanbase/kernel-quickstart)
3. [《数据库管理系统实现》 华中科技大学实现教材](docs/lectures/index.md) 3. [《数据库管理系统实现》 华中科技大学实现教材](docs/src/lectures/index.md)
## 系统架构 ## 系统架构
miniob 整体架构如下图所示: MiniOB 整体架构如下图所示:
![架构](docs/images/miniob-introduction-sql-flow.png) ![架构](docs/src/images/miniob-introduction-sql-flow.png)
其中: 其中:
...@@ -62,11 +62,11 @@ OceanBase 初赛基于一套适合初学者实践的数据库实训平台 miniob ...@@ -62,11 +62,11 @@ OceanBase 初赛基于一套适合初学者实践的数据库实训平台 miniob
### 1. 大赛手把手入门教程 ### 1. 大赛手把手入门教程
[大赛入门教程](https://github.com/oceanbase/kernel-quickstart/blob/V1.0.0/zh-CN/1.database-system-overview/5.miniob-github-gitee-instructions.md) [大赛入门教程](docs/src/game/gitee-instructions.md)
### 2. 大赛赛题 ### 2. 大赛赛题
[赛题介绍](docs/miniob_topics.md) [赛题介绍](docs/src/game/miniob_topics.md)
### 3. 提交测试 ### 3. 提交测试
...@@ -74,7 +74,7 @@ OceanBase 初赛基于一套适合初学者实践的数据库实训平台 miniob ...@@ -74,7 +74,7 @@ OceanBase 初赛基于一套适合初学者实践的数据库实训平台 miniob
在提交前, 请参考并学习 [训练营使用说明](https://ask.oceanbase.com/t/topic/35600372) 在提交前, 请参考并学习 [训练营使用说明](https://ask.oceanbase.com/t/topic/35600372)
客户端输出需要满足一定要求,如果你的测试结果不符合预期,请参考 [miniob 输出约定](docs/miniob-output-convention.md) 客户端输出需要满足一定要求,如果你的测试结果不符合预期,请参考 [miniob 输出约定](docs/src/game/miniob-output-convention.md)
### 4. 大赛FAQ ### 4. 大赛FAQ
...@@ -94,7 +94,7 @@ OceanBase 社区热情欢迎每一位对数据库技术热爱的开发者,期 ...@@ -94,7 +94,7 @@ OceanBase 社区热情欢迎每一位对数据库技术热爱的开发者,期
## License ## License
miniob 采用 [木兰宽松许可证,第2版](https://license.coscl.org.cn/MulanPSL2), 可以自由拷贝和使用源码, 当做修改或分发时, 请遵守 [木兰宽松许可证,第2版](https://license.coscl.org.cn/MulanPSL2). MiniOB 采用 [木兰宽松许可证,第2版](https://license.coscl.org.cn/MulanPSL2), 可以自由拷贝和使用源码, 当做修改或分发时, 请遵守 [木兰宽松许可证,第2版](https://license.coscl.org.cn/MulanPSL2).
## 社区组织 ## 社区组织
......
[book]
language = "cn"
multilingual = false
src = "src"
title = "MiniOB"
[output.html]
git-repository-url = "https://github.com/oceanbase/miniob"
# Summary
- [MiniOB 简介](./miniob-introduction.md)
- [如何编译](./how_to_build.md)
- [开发环境搭建](./dev-env/introduction.md)
- [使用 GitPod 开发 MiniOB](./dev-env/dev_by_gitpod.md)
- [开发环境搭建(本地调试, 适用 Linux 和 Mac)](./dev-env/how_to_dev_miniob_by_vscode.md)
- [开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)](./dev-env/how_to_dev_in_docker_container_by_vscode.md)
- [Windows 使用Docker开发MiniOB](./dev-env/how_to_dev_miniob_by_docker_on_windows.md)
- [使用Docker开发MiniOB](./dev-env/how-to-dev-using-docker.md)
- [功能模块设计说明文档](./design/introduction.md)
- [事务](./design/miniob-transaction.md)
- [CLog](./design/miniob-clog.md)
- [SQL Parser](./design/miniob-sql-parser.md)
- [Doxy代码文档](./design/doxy/html/index.html)
- [OceanBase 数据库大赛](./game/introduction.md)
- [提交测试需要满足的输出要求](./game/miniob-output-convention.md)
- [2021届大赛题目介绍](./game/miniob_topics.md)
- [大赛手把手入门教程](./game/gitee-instructions.md)
- [数据库基础理论课程](./lectures/index.md)
- [第1章 数据库管理系统概述](./lectures/lecture-1.md)
- [第2章 数据库的存储结构](./lectures/lecture-2.md)
- [第3章 索引结构](./lectures/lecture-3.md)
- [第4章 查询处理](./lectures/lecture-4.md)
- [第5章 查询优化](./lectures/lecture-5.md)
- [第6章 事务处理](./lectures/lecture-6.md)
- [参考资料](./lectures/references.md)
- [版权声明](./lectures/copyright.md)
\ No newline at end of file
# 功能模块设计说明
- [事务](./miniob-transaction.md)
- [CLog](./miniob-clog.md)
- [SQL Parser](./miniob-sql-parser.md)
- [Doxy文档](./doxy/html/index.html)
\ No newline at end of file
...@@ -30,6 +30,8 @@ cmake -DCONCURRENCY=ON .. ...@@ -30,6 +30,8 @@ cmake -DCONCURRENCY=ON ..
``` ```
然后在build目录执行 make。编译完成后启动 observer 服务端进程。 然后在build目录执行 make。编译完成后启动 observer 服务端进程。
> 也可以使用 bash build.sh -DCONCURRENCY=ON 来编译
可以在启动observer时,增加 `-t mvcc` 选项来开启MVCC,假设当前目录是build(或build_debug之类): 可以在启动observer时,增加 `-t mvcc` 选项来开启MVCC,假设当前目录是build(或build_debug之类):
```bash ```bash
......
# 搭建开发环境
MiniOB 当前可以在Linux/MacOS上编译,所以开发环境最好是Linux或者MacOS。Windows上可以使用WSL2,或者使用Docker。这里有几个文档,大家可以参考并选择自己的开发环境。另外,很多同学喜欢使用visual studio code开发,MiniOB 中也将vscode的一些配置文件放在了仓库中,比如 .vscode/tasks.json 和 .vscode/launch.json,可以参考使用。
- [使用 GitPod 开发 MiniOB](dev_by_gitpod.md)
- [开发环境搭建(本地调试, 适用 Linux 和 Mac)](how_to_dev_miniob_by_vscode.md)
- [开发环境搭建(远程调试, 适用于 Window, Linux 和 Mac)](how_to_dev_in_docker_container_by_vscode.md)
- [Windows 使用Docker开发MiniOB](how_to_dev_miniob_by_docker_on_windows.md)
- [使用Docker开发MiniOB](how-to-dev-using-docker.md)
\ No newline at end of file
# 1.4 MiniOB Gitee 使用说明
实战 MiniOB 编程需要在 Gitee 上创建自己的 private 仓库,在开发完成后,将代码提交到自己的仓库中,然后在训练营中进行测试。
MiniOB 仓库地址:<https://github.com/oceanbase/miniob>
训练营地址:<https://open.oceanbase.com/train>
本文将以 Gitee 为例介绍如何在训练营中进行提测以及常用的 Git 操作命令。
## Gitee 提测流程
前提条件:已注册 Gitee 账号,Gitee 官网地址:<https://gitee.com>
- 创建私有仓库
1. 登录 Gitee 平台,选择 **新建仓库**
![新建仓库](images/create-repo.png)
2. 输入仓库信息,单击 **创建**。设置为私有仓库后其他人无法查看到你的代码。
![新建仓库](images/create-repo2.png)
- 下载代码
```bash
# 将代码拉到本地
git clone https://github.com/oceanbase/miniob -b miniob_test
```
<main id="notice" type='explain'>
<h4>说明</h4>
<p>若网络状态不好,也可以直接在 GitHub 上下载代码压缩包,下载时需要先选择 miniob_test 分支。</p>
</main>
- 将 MiniOB 代码 push 到自己的仓库
```bash
# 进入到 miniob 目录,删除 .git 目录,清除已有的 git 信息
cd miniob
rm -rf .git
# 重新初始化 git 信息,并将代码提交到自己的仓库
git init
git add .
git commit -m 'init' # 提交所有代码到本地仓库
# 将代码推送到远程仓库
git remote add origin https://gitee.com/xxx/miniob.git # 注意替换命令中的 息为自己的库信息
git branch -M main
git push -u origin main
```
- 赋权官方测试账号
对于私有仓库,默认情况下其他人看不到,同样 OceanBase 测试后台也无法拉取到代码,这时想要提交测试,需要先给 OceanBase 的官方测试账号增加一个权限。
官方测试账号为:`oceanbase-ce-game-test`
首先在网页上打开自己的仓库,然后按照如下顺序操作即可。如果有疑问,也可以在 [OceanBase 社区论坛](https://ask.oceanbase.com/)或钉钉群(33254054)提问。
1. 选择 **管理 > 仓库成员管理 > 观察者**
![管理](images/reporter.png)
2. 选择 **直接添加**,搜索官方测试账号。
![邀请用户](images/invite-users.png)
3. 添加完成后,单击 **提交**
![添加成员](images/add-members.png)
## 日常 Git 开发命令
- 查看当前分支
```bash
git branch # 查看本地分支
git branch -a # 查看所有分支,包括远程分支
```
- 创建分支
```bash
git checkout -b 'your branch name'
git branch -d 'your branch name' # 删除一个分支
```
- 切换分支
```bash
git checkout 'branch name'
```
- 提交代码
```bash
# 添加想要提交的文件或文件夹
git add 'the files or directories you want to commit'
# 这一步也可以用 git add . 添加当前目录
# 提交到本地仓库
# -m 中是提交代码的消息,建议写有意义的信息,方便后面查找
git commit -m 'commit message'
```
- 推送代码到远程仓库
```bash
git push
# 可以将多次提交,一次性 push 到远程仓库
```
- 合并代码
```bash
# 假设当前处于分支 develop 下
git merge feature/update
# 会将 feature/update 分支的修改,merge 到 develop 分支
```
- 临时修改另一个分支的代码
```bash
# 有时候,正在开发一个新功能时,突然来了一个紧急 BUG,这时候需要切换到另一个分 去开发
# 这时可以先把当前的代码提交上去,然后切换分支。
# 或者也可以这样:
git stash # 将当前的修改保存起来
git checkout main # 切换到主分支,或者修复 BUG 的分支
git checkout -b fix/xxx # 创建一个新分支,用于修复问题
# 修改完成后,merge 到 main 分支
# 然后,继续我们的功能开发
git checkout feature/update # 假设我们最开始就是在这个分支上
git stash pop
# stash 还有很多好玩的功能,大家可以探索一下
```
# OceanBase 数据库大赛
2022 OceanBase 数据库大赛是由中国计算机学会(CCF)数据库专业委员会指导,OceanBase 与蚂蚁技术研究院学术合作团队联合举办的数据库内核实战赛事。本次大赛主要面向全国爱好数据库的高校学生,以“竞技、交流、成长”为宗旨,搭建基于赛事的技术交流平台,促进高校创新人才培养机制,不仅帮助学生从0开始系统化学习数据库理论知识,提升学生数据库实践能力,更能帮助学生走向企业积累经验,促进国内数据库人才的发展,碰撞出创新的火花。
更多详情, 请参考 [OceanBase 大赛](https://open.oceanbase.com/competition/index)
在开始参加大赛或者训练营之前,需要创建自己的代码仓库,这里有一个gitee的使用说明:
[大赛手把手入门教程](./gitee-instructions.md)
作为参考,这里有第一届数据库大赛的题目介绍:
[第一届数据库大赛题目介绍](./miniob_topics.md)
在参赛前,除了学习基础的理论知识,还可以使用OceanBase提供的训练营,来快速上手:
[训练营](https://open.oceanbase.com/train?questionId=200001)
训练营的使用方法比较简单,不过这里也有一个小手册:
[训练营使用手册](https://ask.oceanbase.com/t/topic/35600372)
注意,在训练营开始前,需要注意自己的程序输出需要满足一定的要求,请参考:
[提交测试需要满足的输出要求](./miniob-output-convention.md)
我们也收集了一些常见问题,可以参考:
[常见问题](https://ask.oceanbase.com/t/topic/35601465)
# How to build # 如何编译
0. base 0. base
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
作者 华中科技大学谢美意 左琼 作者 华中科技大学谢美意 左琼
[第1章 数据库管理系统概述](lecture-1.md) [第1章 数据库管理系统概述](lecture-1.md)
[第2章 数据库的存储结构](lecture-2.md) [第2章 数据库的存储结构](lecture-2.md)
......
...@@ -34,8 +34,8 @@ class Db; ...@@ -34,8 +34,8 @@ class Db;
/** /**
* @defgroup CLog * @defgroup CLog
* @brief CLog 就是 commit log。或者等价于redo log。
* @file clog.h * @file clog.h
* @brief CLog 就是 commit log
* @details 这个模块想要实现数据库事务中的D(durability),也就是持久化。 * @details 这个模块想要实现数据库事务中的D(durability),也就是持久化。
* 持久化是事务四大特性(ACID)中最复杂的模块,这里的实现简化了99.999%,仅在一些特定场景下才能 * 持久化是事务四大特性(ACID)中最复杂的模块,这里的实现简化了99.999%,仅在一些特定场景下才能
* 恢复数据库。 * 恢复数据库。
...@@ -66,6 +66,7 @@ enum class CLogType ...@@ -66,6 +66,7 @@ enum class CLogType
/** /**
* @brief clog type 转换成字符串 * @brief clog type 转换成字符串
* @ingroup CLog
*/ */
const char *clog_type_name(CLogType type); const char *clog_type_name(CLogType type);
...@@ -76,18 +77,20 @@ int32_t clog_type_to_integer(CLogType type); ...@@ -76,18 +77,20 @@ int32_t clog_type_to_integer(CLogType type);
/** /**
* @brief 数字转换成clog type * @brief 数字转换成clog type
* @ingroup CLog
*/ */
CLogType clog_type_from_integer(int32_t value); CLogType clog_type_from_integer(int32_t value);
/** /**
* @brief CLog的记录头。每个日志都带有这个信息 * @brief CLog的记录头。每个日志都带有这个信息
* @ingroup CLog
*/ */
struct CLogRecordHeader struct CLogRecordHeader
{ {
int32_t lsn_ = -1; /// log sequence number。当前没有使用 int32_t lsn_ = -1; ///< log sequence number。当前没有使用
int32_t trx_id_ = -1; /// 日志所属事务的编号 int32_t trx_id_ = -1; ///< 日志所属事务的编号
int32_t type_ = clog_type_to_integer(CLogType::ERROR); /// 日志类型 int32_t type_ = clog_type_to_integer(CLogType::ERROR); ///< 日志类型
int32_t logrec_len_ = 0; /// record的长度,不包含header长度 int32_t logrec_len_ = 0; ///< record的长度,不包含header长度
bool operator==(const CLogRecordHeader &other) const bool operator==(const CLogRecordHeader &other) const
{ {
...@@ -98,12 +101,13 @@ struct CLogRecordHeader ...@@ -98,12 +101,13 @@ struct CLogRecordHeader
}; };
/** /**
* @ingroup CLog
* @brief MTR_COMMIT 日志的数据 * @brief MTR_COMMIT 日志的数据
* 其它的类型的MTR日志都没有数据,只有COMMIT有。 * @details 其它的类型的MTR日志都没有数据,只有COMMIT有。
*/ */
struct CLogRecordCommitData struct CLogRecordCommitData
{ {
int32_t commit_xid_ = -1; /// 事务提交的事务号 int32_t commit_xid_ = -1; ///< 事务提交的事务号
bool operator == (const CLogRecordCommitData &other) const bool operator == (const CLogRecordCommitData &other) const
{ {
...@@ -115,15 +119,16 @@ struct CLogRecordCommitData ...@@ -115,15 +119,16 @@ struct CLogRecordCommitData
/** /**
* @brief 有具体数据修改的事务日志数据 * @brief 有具体数据修改的事务日志数据
* @ingroup CLog
* @details 这里记录的都是操作的记录,比如插入、删除一条数据。 * @details 这里记录的都是操作的记录,比如插入、删除一条数据。
*/ */
struct CLogRecordData struct CLogRecordData
{ {
int32_t table_id_ = -1; /// 操作的表 int32_t table_id_ = -1; ///< 操作的表
RID rid_; /// 操作的哪条记录 RID rid_; ///< 操作的哪条记录
int32_t data_len_ = 0; /// 记录的数据长度(因为header中也包含长度信息,这个长度可以不要) int32_t data_len_ = 0; ///< 记录的数据长度(因为header中也包含长度信息,这个长度可以不要)
int32_t data_offset_ = 0; /// 操作的数据在完整记录中的偏移量 int32_t data_offset_ = 0; ///< 操作的数据在完整记录中的偏移量
char * data_ = nullptr; /// 具体的数据,可能没有任何数据 char * data_ = nullptr; ///< 具体的数据,可能没有任何数据
~CLogRecordData(); ~CLogRecordData();
...@@ -138,11 +143,12 @@ struct CLogRecordData ...@@ -138,11 +143,12 @@ struct CLogRecordData
std::string to_string() const; std::string to_string() const;
const static int32_t HEADER_SIZE; /// 指RecordData的头长度,即不包含data_的长度 const static int32_t HEADER_SIZE; ///< 指RecordData的头长度,即不包含data_的长度
}; };
/** /**
* @brief 表示一条日志记录 * @brief 表示一条日志记录
* @ingroup CLog
* @details 一条日志记录由一个日志头和具体的数据构成。 * @details 一条日志记录由一个日志头和具体的数据构成。
* 具体的数据根据日志类型不同,也是不同的类型。 * 具体的数据根据日志类型不同,也是不同的类型。
*/ */
...@@ -215,14 +221,15 @@ public: ...@@ -215,14 +221,15 @@ public:
std::string to_string() const; std::string to_string() const;
protected: protected:
CLogRecordHeader header_; /// 日志头信息 CLogRecordHeader header_; ///< 日志头信息
CLogRecordData data_record_; /// 如果日志操作的是数据,此结构生效 CLogRecordData data_record_; ///< 如果日志操作的是数据,此结构生效
CLogRecordCommitData commit_record_; /// 如果是事务提交日志,此结构生效 CLogRecordCommitData commit_record_; ///< 如果是事务提交日志,此结构生效
}; };
/** /**
* @brief 缓存运行时产生的日志对象 * @brief 缓存运行时产生的日志对象
* @ingroup CLog
* @details 当前的实现非常简单,没有采用其它数据库中常用的将日志序列化到二进制buffer, * @details 当前的实现非常简单,没有采用其它数据库中常用的将日志序列化到二进制buffer,
* 管理二进制buffer的方法。这里仅仅把日志记录下来,放到链表中。如果达到一定量的日志, * 管理二进制buffer的方法。这里仅仅把日志记录下来,放到链表中。如果达到一定量的日志,
* 或者日志数量超过某个阈值,就会调用flush_buffer将日志刷新到磁盘中。 * 或者日志数量超过某个阈值,就会调用flush_buffer将日志刷新到磁盘中。
...@@ -256,13 +263,14 @@ private: ...@@ -256,13 +263,14 @@ private:
RC write_log_record(CLogFile &log_file, CLogRecord *log_record); RC write_log_record(CLogFile &log_file, CLogRecord *log_record);
private: private:
common::Mutex lock_; /// 加锁支持多线程并发写入 common::Mutex lock_; ///< 加锁支持多线程并发写入
std::deque<std::unique_ptr<CLogRecord>> log_records_; /// 当前等待刷数据的日志记录 std::deque<std::unique_ptr<CLogRecord>> log_records_; ///< 当前等待刷数据的日志记录
std::atomic_int32_t total_size_; /// 当前缓存中的日志记录的总大小 std::atomic_int32_t total_size_; ///< 当前缓存中的日志记录的总大小
}; };
/** /**
* @brief 读写日志文件 * @brief 读写日志文件
* @ingroup CLog
* @details 这里的名字不太贴切,因为这个类希望管理所有日志文件,而不是特定的某个文件。不过当前 * @details 这里的名字不太贴切,因为这个类希望管理所有日志文件,而不是特定的某个文件。不过当前
* 只有一个文件,并且文件名是固定的。 * 只有一个文件,并且文件名是固定的。
*/ */
...@@ -312,13 +320,14 @@ public: ...@@ -312,13 +320,14 @@ public:
bool eof() const { return eof_; } bool eof() const { return eof_; }
protected: protected:
std::string filename_; /// 日志文件名。总是init函数参数path路径下的clog文件 std::string filename_; ///< 日志文件名。总是init函数参数path路径下的clog文件
int fd_ = -1; /// 操作的文件描述符 int fd_ = -1; ///< 操作的文件描述符
bool eof_ = false; /// 是否已经读取到文件尾 bool eof_ = false; ///< 是否已经读取到文件尾
}; };
/** /**
* @brief 日志记录遍历器 * @brief 日志记录遍历器
* @ingroup CLog
* @details 使用时先执行初始化(init),然后多次调用next,直到valid返回false。 * @details 使用时先执行初始化(init),然后多次调用next,直到valid返回false。
*/ */
class CLogRecordIterator class CLogRecordIterator
...@@ -340,6 +349,7 @@ private: ...@@ -340,6 +349,7 @@ private:
/** /**
* @brief 日志管理器 * @brief 日志管理器
* @ingroup CLog
* @details 一个日志管理器属于某一个DB(当前仅有一个DB sys)。 * @details 一个日志管理器属于某一个DB(当前仅有一个DB sys)。
* 管理器负责写日志(运行时)、读日志与恢复(启动时) * 管理器负责写日志(运行时)、读日志与恢复(启动时)
*/ */
...@@ -407,6 +417,6 @@ public: ...@@ -407,6 +417,6 @@ public:
RC recover(Db *db); RC recover(Db *db);
private: private:
CLogBuffer *log_buffer_ = nullptr; /// 日志缓存。新增日志时先放到内存,也就是这个buffer中 CLogBuffer *log_buffer_ = nullptr; ///< 日志缓存。新增日志时先放到内存,也就是这个buffer中
CLogFile * log_file_ = nullptr; /// 管理日志,比如读写日志 CLogFile * log_file_ = nullptr; ///< 管理日志,比如读写日志
}; };
...@@ -27,11 +27,10 @@ class Table; ...@@ -27,11 +27,10 @@ class Table;
/** /**
* @defgroup RecordManager * @defgroup RecordManager
* @file record_manager.h
*
* @brief 这里负责管理在一个文件上表记录(行)的组织/管理 * @brief 这里负责管理在一个文件上表记录(行)的组织/管理
* @file record_manager.h
* *
* 表记录管理的内容包括如何在文件上存放、读取、检索。也就是记录的增删改查。 * @details 表记录管理的内容包括如何在文件上存放、读取、检索。也就是记录的增删改查。
* 这里的文件都会被拆分成页面,每个页面都有一样的大小。更详细的信息可以参考BufferPool。 * 这里的文件都会被拆分成页面,每个页面都有一样的大小。更详细的信息可以参考BufferPool。
* 按照BufferPool的设计,第一个页面用来存放BufferPool本身的元数据,比如当前文件有多少页面、已经分配了多少页面、 * 按照BufferPool的设计,第一个页面用来存放BufferPool本身的元数据,比如当前文件有多少页面、已经分配了多少页面、
* 每个页面的分配状态等。所以第一个页面对RecordManager来说没有作用。RecordManager 本身没有再单独拿一个页面 * 每个页面的分配状态等。所以第一个页面对RecordManager来说没有作用。RecordManager 本身没有再单独拿一个页面
...@@ -55,24 +54,24 @@ class Table; ...@@ -55,24 +54,24 @@ class Table;
*/ */
/** /**
* 数据文件,按照页面来组织,每一页都存放一些记录/数据行 * @brief 数据文件,按照页面来组织,每一页都存放一些记录/数据行
* 每一页都有一个这样的页头,虽然看起来浪费,但是现在就简单的这么做 * @ingroup RecordManager
* @details 每一页都有一个这样的页头,虽然看起来浪费,但是现在就简单的这么做
* 从这个页头描述的信息来看,当前仅支持定长行/记录。如果要支持变长记录, * 从这个页头描述的信息来看,当前仅支持定长行/记录。如果要支持变长记录,
* 或者超长(超出一页)的记录,这么做是不合适的。 * 或者超长(超出一页)的记录,这么做是不合适的。
*/ */
struct PageHeader struct PageHeader
{ {
int32_t record_num; /// 当前页面记录的个数 int32_t record_num; ///< 当前页面记录的个数
int32_t record_capacity; /// 最大记录个数 int32_t record_capacity; ///< 最大记录个数
int32_t record_real_size; // 每条记录的实际大小 int32_t record_real_size; ///< 每条记录的实际大小
int32_t record_size; // 每条记录占用实际空间大小(可能对齐) int32_t record_size; ///< 每条记录占用实际空间大小(可能对齐)
int32_t first_record_offset; // 第一条记录的偏移量 int32_t first_record_offset; ///< 第一条记录的偏移量
}; };
/** /**
* @ingroup RecordManager
*
* @brief 遍历一个页面中每条记录的iterator * @brief 遍历一个页面中每条记录的iterator
* @ingroup RecordManager
*/ */
class RecordPageIterator class RecordPageIterator
{ {
...@@ -96,14 +95,14 @@ public: ...@@ -96,14 +95,14 @@ public:
private: private:
RecordPageHandler *record_page_handler_ = nullptr; RecordPageHandler *record_page_handler_ = nullptr;
PageNum page_num_ = BP_INVALID_PAGE_NUM; PageNum page_num_ = BP_INVALID_PAGE_NUM;
common::Bitmap bitmap_; // bitmap 的相关信息可以参考 RecordPageHandler 的说明 common::Bitmap bitmap_; ///< bitmap 的相关信息可以参考 RecordPageHandler 的说明
SlotNum next_slot_num_ = 0; // 当前遍历到了哪一个slot SlotNum next_slot_num_ = 0; ///< 当前遍历到了哪一个slot
}; };
/** /**
* @brief 负责处理一个页面中各种操作,比如插入记录、删除记录或者查找记录 * @brief 负责处理一个页面中各种操作,比如插入记录、删除记录或者查找记录
* * @ingroup RecordManager
* 当前定长记录模式下每个页面的组织大概是这样的: * @details 当前定长记录模式下每个页面的组织大概是这样的:
* | PageHeader | record allocate bitmap | * | PageHeader | record allocate bitmap |
* |------------|------------------------| * |------------|------------------------|
* | record1 | record2 | ..... | recordN | * | record1 | record2 | ..... | recordN |
...@@ -190,11 +189,11 @@ protected: ...@@ -190,11 +189,11 @@ protected:
} }
protected: protected:
DiskBufferPool *disk_buffer_pool_ = nullptr; /// 当前操作的buffer pool(文件) DiskBufferPool *disk_buffer_pool_ = nullptr; ///< 当前操作的buffer pool(文件)
bool readonly_ = false; /// 当前的操作是否都是只读的 bool readonly_ = false; ///< 当前的操作是否都是只读的
Frame *frame_ = nullptr; /// 当前操作页面关联的frame(frame的更多概念可以参考buffer pool和frame) Frame *frame_ = nullptr; ///< 当前操作页面关联的frame(frame的更多概念可以参考buffer pool和frame)
PageHeader *page_header_ = nullptr; /// 当前页面上页面头 PageHeader *page_header_ = nullptr; ///< 当前页面上页面头
char *bitmap_ = nullptr; /// 当前页面上record分配状态信息bitmap内存起始位置 char *bitmap_ = nullptr; ///< 当前页面上record分配状态信息bitmap内存起始位置
private: private:
friend class RecordPageIterator; friend class RecordPageIterator;
...@@ -202,7 +201,8 @@ private: ...@@ -202,7 +201,8 @@ private:
/** /**
* @brief 管理整个文件中记录的增删改查 * @brief 管理整个文件中记录的增删改查
* 整个文件的组织格式请参考该文件中最前面的注释 * @ingroup RecordManager
* @details 整个文件的组织格式请参考该文件中最前面的注释
*/ */
class RecordFileHandler class RecordFileHandler
{ {
...@@ -223,18 +223,18 @@ public: ...@@ -223,18 +223,18 @@ public:
void close(); void close();
/** /**
* 从指定文件中删除标识符为rid的记录 * @brief 从指定文件中删除标识符为rid的记录
*/ */
RC delete_record(const RID *rid); RC delete_record(const RID *rid);
/** /**
* 插入一个新的记录到指定文件中,data为指向新纪录内容的指针,返回该记录的标识符rid * @brief 插入一个新的记录到指定文件中,data为指向新纪录内容的指针,返回该记录的标识符rid
*/ */
RC insert_record(const char *data, int record_size, RID *rid); RC insert_record(const char *data, int record_size, RID *rid);
RC recover_insert_record(const char *data, int record_size, const RID &rid); RC recover_insert_record(const char *data, int record_size, const RID &rid);
/** /**
* 获取指定文件中标识符为rid的记录内容到rec指向的记录结构中 * @brief 获取指定文件中标识符为rid的记录内容到rec指向的记录结构中
* @param page_handler[in] * @param page_handler[in]
* 访问记录时,会拿住一些资源不释放,比如页面锁,使用这个对象保存相关的资源,并在析构时会自动释放 * 访问记录时,会拿住一些资源不释放,比如页面锁,使用这个对象保存相关的资源,并在析构时会自动释放
* @param rid 想要获取的记录ID * @param rid 想要获取的记录ID
...@@ -262,13 +262,14 @@ private: ...@@ -262,13 +262,14 @@ private:
private: private:
DiskBufferPool *disk_buffer_pool_ = nullptr; DiskBufferPool *disk_buffer_pool_ = nullptr;
std::unordered_set<PageNum> free_pages_; /// 没有填充满的页面集合 std::unordered_set<PageNum> free_pages_; ///< 没有填充满的页面集合
common::Mutex lock_; /// 当编译时增加-DCONCURRENCY=ON 选项时,才会真正的支持并发 common::Mutex lock_; ///< 当编译时增加-DCONCURRENCY=ON 选项时,才会真正的支持并发
}; };
/** /**
* @brief 遍历某个文件中所有记录 * @brief 遍历某个文件中所有记录
* 遍历所有的页面,同时访问这些页面中所有的记录 * @ingroup RecordManager
* @details 遍历所有的页面,同时访问这些页面中所有的记录
*/ */
class RecordFileScanner class RecordFileScanner
{ {
...@@ -277,8 +278,8 @@ public: ...@@ -277,8 +278,8 @@ public:
~RecordFileScanner(); ~RecordFileScanner();
/** /**
* 打开一个文件扫描。 * @brief 打开一个文件扫描。
* 如果条件不为空,则要对每条记录进行条件比较,只有满足所有条件的记录才被返回 * @details 如果条件不为空,则要对每条记录进行条件比较,只有满足所有条件的记录才被返回
* @param table 遍历的哪张表 * @param table 遍历的哪张表
* @param buffer_pool 访问的文件 * @param buffer_pool 访问的文件
* @param readonly 当前是否只读操作。访问数据时,需要对页面加锁。比如 * @param readonly 当前是否只读操作。访问数据时,需要对页面加锁。比如
...@@ -288,27 +289,43 @@ public: ...@@ -288,27 +289,43 @@ public:
RC open_scan(Table *table, DiskBufferPool &buffer_pool, Trx *trx, bool readonly, ConditionFilter *condition_filter); RC open_scan(Table *table, DiskBufferPool &buffer_pool, Trx *trx, bool readonly, ConditionFilter *condition_filter);
/** /**
* 关闭一个文件扫描,释放相应的资源 * @brief 关闭一个文件扫描,释放相应的资源
*/ */
RC close_scan(); RC close_scan();
/**
* @brief 判断是否还有数据
* @details 判断完成后调用next获取下一条数据
*/
bool has_next(); bool has_next();
/**
* @brief 获取下一条记录
* @details 获取下一条记录之前先调用has_next()判断是否还有数据
*/
RC next(Record &record); RC next(Record &record);
private: private:
/**
* @brief 获取下一条记录
*/
RC fetch_next_record(); RC fetch_next_record();
/**
* @brief 获取一个页面内的下一条记录
*/
RC fetch_next_record_in_page(); RC fetch_next_record_in_page();
private: private:
// TODO 对于一个纯粹的record遍历器来说,不应该关心表和事务 // TODO 对于一个纯粹的record遍历器来说,不应该关心表和事务
Table *table_ = nullptr; /// 当前遍历的是哪张表。这个字段仅供事务函数使用,如果设计合适,可以去掉 Table *table_ = nullptr; ///< 当前遍历的是哪张表。这个字段仅供事务函数使用,如果设计合适,可以去掉
DiskBufferPool *disk_buffer_pool_ = nullptr; /// 当前访问的文件 DiskBufferPool *disk_buffer_pool_ = nullptr; ///< 当前访问的文件
Trx *trx_ = nullptr; /// 当前是哪个事务在遍历 Trx *trx_ = nullptr; ///< 当前是哪个事务在遍历
bool readonly_ = false; /// 遍历出来的数据,是否可能对它做修改 bool readonly_ = false; ///< 遍历出来的数据,是否可能对它做修改
BufferPoolIterator bp_iterator_; /// 遍历buffer pool的所有页面 BufferPoolIterator bp_iterator_; ///< 遍历buffer pool的所有页面
ConditionFilter *condition_filter_ = nullptr; /// 过滤record ConditionFilter *condition_filter_ = nullptr; ///< 过滤record
RecordPageHandler record_page_handler_; RecordPageHandler record_page_handler_;
RecordPageIterator record_page_iterator_; /// 遍历某个页面上的所有record RecordPageIterator record_page_iterator_; ///< 遍历某个页面上的所有record
Record next_record_; Record next_record_; ///< 获取的记录放在这里缓存起来
}; };
...@@ -26,8 +26,8 @@ See the Mulan PSL v2 for more details. */ ...@@ -26,8 +26,8 @@ See the Mulan PSL v2 for more details. */
#include "common/rc.h" #include "common/rc.h"
/** /**
* @defgroup Transaction 事务模块 * @defgroup Transaction
* @brief 描述事务相关的代码 * @brief 事务相关的内容
*/ */
class Db; class Db;
...@@ -37,11 +37,16 @@ class Trx; ...@@ -37,11 +37,16 @@ class Trx;
/** /**
* @brief 描述一个操作,比如插入、删除行等 * @brief 描述一个操作,比如插入、删除行等
* @ingroup Transaction
* @details 通常包含一个操作的类型,以及操作的对象和具体的数据 * @details 通常包含一个操作的类型,以及操作的对象和具体的数据
*/ */
class Operation class Operation
{ {
public: public:
/**
* @brief 操作的类型
* @ingroup Transaction
*/
enum class Type : int enum class Type : int
{ {
INSERT, INSERT,
...@@ -65,8 +70,9 @@ public: ...@@ -65,8 +70,9 @@ public:
SlotNum slot_num() const { return slot_num_; } SlotNum slot_num() const { return slot_num_; }
private: private:
///< 操作的哪张表。这里直接使用表其实并不准确,因为表中的索引也可能有日志
Type type_; Type type_;
/// 操作的哪张表。这里直接使用表其实并不准确,因为表中的索引也可能有日志
Table * table_ = nullptr; Table * table_ = nullptr;
PageNum page_num_; // TODO use RID instead of page num and slot num PageNum page_num_; // TODO use RID instead of page num and slot num
SlotNum slot_num_; SlotNum slot_num_;
...@@ -91,13 +97,22 @@ public: ...@@ -91,13 +97,22 @@ public:
} }
}; };
/**
* @brief 事务管理器
* @ingroup Transaction
*/
class TrxKit class TrxKit
{ {
public: public:
/**
* @brief 事务管理器的类型
* @ingroup Transaction
* @details 进程启动时根据事务管理器的类型来创建具体的对象
*/
enum Type enum Type
{ {
VACUOUS, VACUOUS, ///< 空的事务管理器,不做任何事情
MVCC, MVCC, ///< 支持MVCC的事务管理器
}; };
public: public:
...@@ -119,6 +134,10 @@ public: ...@@ -119,6 +134,10 @@ public:
static TrxKit *instance(); static TrxKit *instance();
}; };
/**
* @brief 事务接口
* @ingroup Transaction
*/
class Trx class Trx
{ {
public: public:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册