[{"data":1,"prerenderedAt":322},["ShallowReactive",2],{"content:\u002Fprojects\u002Fmydb\u002Fmydb0":3,"surround:\u002Fprojects\u002Fmydb\u002Fmydb0":233,"github:CN-GuoZiyang\u002FMYDB":239},{"id":4,"title":5,"body":6,"categories":209,"date":211,"description":212,"draft":213,"extension":214,"image":215,"meta":216,"navigation":218,"path":219,"permalink":215,"published":215,"readingTime":220,"recommend":215,"references":215,"seo":225,"sitemap":226,"stem":227,"tags":228,"type":231,"__hash__":232},"content\u002Fposts\u002Fprojects\u002Fmydb\u002Fmydb0.md","MYDB 0. 项目结构和一些不得不说的话",{"type":7,"value":8,"toc":201},"minimark",[9,19,23,28,31,34,37,40,43,58,61,64,67,70,89,92,99,102,105,122,125,128,137,140,145,148,151,162,165,171,174,180,183,189,192,195],[10,11,12,13],"p",{},"项目地址：",[14,15,16],"a",{"href":16,"rel":17},"https:\u002F\u002Fgithub.com\u002FCN-GuoZiyang\u002FMYDB",[18],"nofollow",[20,21],"github",{"repo":22},"CN-GuoZiyang\u002FMYDB",[24,25,27],"h3",{"id":26},"前言一些废话","前言（一些废话）",[10,29,30],{},"或许是造轮子上瘾了，也有可能只是觉得需要补一补数据库的基本原理，大概花了大半个月，利用下班到半夜这段时间，我做完了这个项目。",[10,32,33],{},"和数据库也算有点渊源的，在学校开设数据库系统这门课的时候，我恰巧在深圳实习。于是乎，上网课成了我实习期间名正言顺的摸鱼理由，除了听课，其他啥都干。同样，操作系统也是在那个时候教授的，因为我对 OS 还是有点兴趣的，所以学得没有 DB 那么烂。",[10,35,36],{},"很快副作用就来了，字节二面的时候，面试官问我对数据库了解怎么样，本着坦诚清晰的原则，我说“一点也不了解”，于是又问我 redis 呢，我也只好说“也不了解”。好在面试官倒也没计较，还让我过了。就是不知道这俩“不知道”有没有拖烂我的面评……",[10,38,39],{},"工作之后，组里的内容和数据库倒也没有什么关系，本以为就此远离了数据库和 CRUD，没想到变化来得如此的快，隔壁资管组急缺人，向部门申请调人力支援，于是我就被弄过去支援了。资管对于一致性要求颇高，自然不能像原来一样，啥数据都往 redis 塞，没塞进去也没关系了……",[24,41,42],{"id":42},"契机",[10,44,45,46,51,52,57],{},"某天在 Github 网上冲浪的时候，偶然就看到了 ",[14,47,50],{"href":48,"rel":49},"https:\u002F\u002Fgithub.com\u002Fqw4990",[18],"@qw4990"," 大佬的数据库项目：",[14,53,56],{"href":54,"rel":55},"https:\u002F\u002Fgithub.com\u002Fqw4990\u002FNYADB2",[18],"NYADB2","。这是一个用 golang 实现的一个简单的数据库，分层设计及其优秀，代码也便于阅读。出于对 Java 的念念不忘，我就依据这个项目的基本架构，写一个 Java 版的 DB，实现过程中，有许多细节都参照了这个项目。",[10,59,60],{},"令人汗颜的是，这个项目是作者本科的兴趣项目，也许这就是大佬吧（逃",[10,62,63],{},"RESPECT",[24,65,66],{"id":66},"整体结构",[10,68,69],{},"MYDB 分为后端和前端，前后端通过 socket 进行交互。前端（客户端）的职责很单一，读取用户输入，并发送到后端执行，输出返回结果，并等待下一次输入。MYDB 后端则需要解析 SQL，如果是合法的 SQL，就尝试执行并返回结果。不包括解析器，MYDB 的后端划分为五个模块，每个模块都又一定的职责，通过接口向其依赖的模块提供方法。五个模块如下：",[71,72,73,77,80,83,86],"ol",{},[74,75,76],"li",{},"Transaction Manager (TM)",[74,78,79],{},"Data Manager (DM)",[74,81,82],{},"Version Manager (VM)",[74,84,85],{},"Index Manager (IM)",[74,87,88],{},"Table Manager (TBM)",[10,90,91],{},"五个模块的依赖关系如下：",[10,93,94],{},[95,96],"img",{"alt":97,"src":98},"MYDB 模块依赖","https:\u002F\u002Fblog-img.774352199.xyz\u002F2025\u002Fb536d4e4ea0ec97d629d82ffde917c54.jpg",[10,100,101],{},"从这个依赖图中，拓扑排序一下就能看出实现顺序。本教程的实现顺序是 TM -> DM -> VM -> IM -> TBM",[10,103,104],{},"每个模块的职责如下：",[71,106,107,110,113,116,119],{},[74,108,109],{},"TM 通过维护 XID 文件来维护事务的状态，并提供接口供其他模块来查询某个事务的状态。",[74,111,112],{},"DM 直接管理数据库 DB 文件和日志文件。DM 的主要职责有：1) 分页管理 DB 文件，并进行缓存；2) 管理日志文件，保证在发生错误时可以根据日志进行恢复；3) 抽象 DB 文件为 DataItem 供上层模块使用，并提供缓存。",[74,114,115],{},"VM 基于两段锁协议实现了调度序列的可串行化，并实现了 MVCC 以消除读写阻塞。同时实现了两种隔离级别。",[74,117,118],{},"IM 实现了基于 B+ 树的索引，BTW，目前 where 只支持已索引字段。",[74,120,121],{},"TBM 实现了对字段和表的管理。同时，解析 SQL 语句，并根据语句操作表。",[24,123,124],{"id":124},"开发环境和运行示例",[10,126,127],{},"项目开发时使用的 WSL2 和 JDK11，如果要在 Windows 上执行，请替换启动参数中的路径为 Windows，JDK 版本要保证在 11 或以上，不兼容 JDK 8（或者可以自行寻找不兼容的方法，替换为兼容即可，应该只有个别方法不兼容）。",[10,129,130],{},[131,132,133],"strong",{},[134,135,136],"em",{},"目前已经兼容 JDK 8",[10,138,139],{},"几乎每个模块和子模块都在 test 文件夹中有对应的单测，同学们一定也要多写写单测，不然到后面一跑起来都不知道 bug 从哪来的。",[10,141,142],{},[131,143,144],{},"不写单测一时爽，出了 bug 火葬场（",[10,146,147],{},"注意首先需要在 pom.xml 中调整编译版本，如果导入 IDE，请更改项目的编译版本以适应你的 JDK",[10,149,150],{},"首先执行以下命令编译源码：",[152,153,159],"pre",{"className":154,"code":156,"language":157,"meta":158},[155],"language-shell","mvn compile\n","shell","",[160,161,156],"code",{"__ignoreMap":158},[10,163,164],{},"接着执行以下命令以 \u002Ftmp\u002Fmydb 作为路径创建数据库：",[152,166,169],{"className":167,"code":168,"language":157,"meta":158},[155],"mvn exec:java -Dexec.mainClass=\"top.guoziyang.mydb.backend.Launcher\" -Dexec.args=\"-create \u002Ftmp\u002Fmydb\"\n",[160,170,168],{"__ignoreMap":158},[10,172,173],{},"随后通过以下命令以默认参数启动数据库服务：",[152,175,178],{"className":176,"code":177,"language":157,"meta":158},[155],"mvn exec:java -Dexec.mainClass=\"top.guoziyang.mydb.backend.Launcher\" -Dexec.args=\"-open \u002Ftmp\u002Fmydb\"\n",[160,179,177],{"__ignoreMap":158},[10,181,182],{},"这时数据库服务就已经启动在本机的 9999 端口。重新启动一个终端，执行以下命令启动客户端连接数据库：",[152,184,187],{"className":185,"code":186,"language":157,"meta":158},[155],"mvn exec:java -Dexec.mainClass=\"top.guoziyang.mydb.client.Launcher\"\n",[160,188,186],{"__ignoreMap":158},[10,190,191],{},"会启动一个交互式命令行，就可以在这里输入类 SQL 语法，回车会发送语句到服务，并输出执行的结果。",[10,193,194],{},"一个执行示例：",[10,196,197],{},[95,198],{"alt":199,"src":200},"MYDB 运行示例","https:\u002F\u002Fblog-img.774352199.xyz\u002F2025\u002Fe0ab6dcbb970d6435a5d5be24f085de8.jpg",{"title":158,"searchDepth":202,"depth":202,"links":203},4,[204,206,207,208],{"id":26,"depth":205,"text":27},3,{"id":42,"depth":205,"text":42},{"id":66,"depth":205,"text":66},{"id":124,"depth":205,"text":124},[210],"项目","2021-11-27 14:43:00","MYDB 项目是一个旨在探索和实现数据库基本原理的个人作品，经历了大半个月的努力，在闲暇时间逐步完成。我在学校学习数据库系统的过程中，积累了一些基础知识，尽管在实习期间更多是借机“摸鱼”。在面试时的坦诚回答虽未造成太大影响，但也促使他重新审视数据库的知识，决定主动学习和实践，从而推动了这个项目的诞生。",false,"md",null,{"slots":217},{},true,"\u002Fprojects\u002Fmydb\u002Fmydb0",{"text":221,"minutes":222,"time":223,"words":224},"7 min read",6.47,388200,1294,{"title":5,"description":212},{"loc":219},"posts\u002Fprojects\u002Fmydb\u002Fmydb0",[229,230],"java","mydb","tech","vNCtjvVRJo88FJg7M5jMJ7fzGMRndiAepp_B54QxFp8",[215,234],{"title":235,"path":236,"stem":237,"date":238,"type":231,"children":-1},"MYDB 1. 从最简单的 TM 开始","\u002Fprojects\u002Fmydb\u002Fmydb1","posts\u002Fprojects\u002Fmydb\u002Fmydb1","2021-11-28 16:10:00",{"id":240,"node_id":241,"name":242,"full_name":243,"private":213,"owner":244,"html_url":262,"description":263,"fork":213,"url":264,"forks_url":265,"keys_url":266,"collaborators_url":267,"teams_url":268,"hooks_url":269,"issue_events_url":270,"events_url":271,"assignees_url":272,"branches_url":273,"tags_url":274,"blobs_url":275,"git_tags_url":276,"git_refs_url":277,"trees_url":278,"statuses_url":279,"languages_url":280,"stargazers_url":281,"contributors_url":282,"subscribers_url":283,"subscription_url":284,"commits_url":285,"git_commits_url":286,"comments_url":287,"issue_comment_url":288,"contents_url":289,"compare_url":290,"merges_url":291,"archive_url":292,"downloads_url":293,"issues_url":294,"pulls_url":295,"milestones_url":296,"notifications_url":297,"labels_url":298,"releases_url":299,"deployments_url":300,"created_at":301,"updated_at":302,"pushed_at":303,"git_url":304,"ssh_url":305,"clone_url":306,"svn_url":262,"homepage":215,"size":307,"stargazers_count":308,"watchers_count":308,"language":309,"has_issues":218,"has_projects":218,"has_downloads":213,"has_wiki":218,"has_pages":213,"has_discussions":213,"forks_count":310,"mirror_url":215,"archived":213,"disabled":213,"open_issues_count":311,"license":312,"allow_forking":218,"is_template":213,"web_commit_signoff_required":213,"has_pull_requests":218,"pull_request_creation_policy":318,"topics":319,"visibility":261,"forks":310,"open_issues":311,"watchers":308,"default_branch":320,"temp_clone_token":215,"network_count":310,"subscribers_count":321},415623738,"R_kgDOGMXqOg","MYDB","senshinya\u002FMYDB",{"login":245,"id":246,"node_id":247,"avatar_url":248,"gravatar_id":158,"url":249,"html_url":250,"followers_url":251,"following_url":252,"gists_url":253,"starred_url":254,"subscriptions_url":255,"organizations_url":256,"repos_url":257,"events_url":258,"received_events_url":259,"type":260,"user_view_type":261,"site_admin":213},"senshinya",155552943,"U_kgDOCUWMrw","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F155552943?v=4","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya","https:\u002F\u002Fgithub.com\u002Fsenshinya","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Ffollowers","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Ffollowing{\u002Fother_user}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Fgists{\u002Fgist_id}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Fstarred{\u002Fowner}{\u002Frepo}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Fsubscriptions","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Forgs","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Frepos","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Fevents{\u002Fprivacy}","https:\u002F\u002Fapi.github.com\u002Fusers\u002Fsenshinya\u002Freceived_events","User","public","https:\u002F\u002Fgithub.com\u002Fsenshinya\u002FMYDB","一个简单的数据库实现","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fforks","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fkeys{\u002Fkey_id}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fcollaborators{\u002Fcollaborator}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fteams","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fhooks","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fissues\u002Fevents{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fevents","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fassignees{\u002Fuser}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fbranches{\u002Fbranch}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Ftags","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fgit\u002Fblobs{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fgit\u002Ftags{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fgit\u002Frefs{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fgit\u002Ftrees{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fstatuses\u002F{sha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Flanguages","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fstargazers","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fcontributors","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fsubscribers","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fsubscription","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fcommits{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fgit\u002Fcommits{\u002Fsha}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fcomments{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fissues\u002Fcomments{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fcontents\u002F{+path}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fcompare\u002F{base}...{head}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fmerges","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002F{archive_format}{\u002Fref}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fdownloads","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fissues{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fpulls{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fmilestones{\u002Fnumber}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fnotifications{?since,all,participating}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Flabels{\u002Fname}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Freleases{\u002Fid}","https:\u002F\u002Fapi.github.com\u002Frepos\u002Fsenshinya\u002FMYDB\u002Fdeployments","2021-10-10T15:24:43Z","2026-08-22T12:44:28Z","2024-02-06T09:29:27Z","git:\u002F\u002Fgithub.com\u002Fsenshinya\u002FMYDB.git","git@github.com:senshinya\u002FMYDB.git","https:\u002F\u002Fgithub.com\u002Fsenshinya\u002FMYDB.git",110,1167,"Java",278,19,{"key":313,"name":314,"spdx_id":315,"url":316,"node_id":317},"gpl-3.0","GNU General Public License v3.0","GPL-3.0","https:\u002F\u002Fapi.github.com\u002Flicenses\u002Fgpl-3.0","MDc6TGljZW5zZTk=","all",[],"master",5,1787554446025]