简介:这是一款面向数据库开发人员、DBA及IT项目文档工程师的自动化数据字典生成工具,专为解决手动编写和维护数据库文档耗时易错、版本不一致等痛点而设计。工具支持MySQL、SQL Server、Oracle等主流数据库,可一键扫描表结构、字段类型、约束、注释并生成HTML/Word/PDF等格式的规范文档,显著提升数据库设计、交接与审计效率。资源包共16个文件(2.58MB),含核心可执行程序DBDocumentGenerator.exe、OpenXML与MySQL驱动DLL、关系图GIF、模板配置XML/CSS/JS、说明文档(ReadMe.txt、TEST.txt)及DOCX/HTML示例,体现开箱即用的工程化交付特点。目前已有531人学习下载,用户可直接运行EXE生成可视化字典,结合模板定制输出样式,并通过配套资源快速理解字段映射逻辑与文档生成流程,是中小型项目数据库文档标准化落地的实用型工具包。
1. 数据字典工具:不是文档生成器,而是数据库的“活体索引”和协作中枢
你有没有遇到过这样的场景:刚接手一个遗留系统,表名是t_usr_inf_v2_bak_2023,字段叫is_del_flag_y_n,注释栏空着,ER 图早就不更新了;或者开发改了个字段类型,测试还在用旧版接口文档跑用例,线上报错才翻出 DDL;更常见的是——DBA 手动维护一份 Excel 字典,但每次发版后没人同步,三个月后它比数据库还“稳定”。这不是个文档问题,是数据契约失效。这份「数据字典工具」不是把SHOW CREATE TABLE结果贴进 Word 的脚本,而是一套可嵌入 CI/CD、支持多源比对、带版本快照、能自动校验字段语义一致性的轻量级 CLI + Web 组合体。它不替代数据库管理平台,但能让你在git diff里一眼看出user_profile表新增了last_login_at_utc字段且被标注为「强制非空,用于风控会话超时计算」。适合中小团队的数据工程师、后端主程、以及需要交付可审计数据资产的交付型项目。
2. 为什么选这套方案:从“导出文档”到“契约驱动”的三层跃迁
2.1 传统方案的三个断层:导出、静态、脱节
多数人第一反应是mysqldump --no-data或 Navicat 的“导出表结构”,但这只解决第一层:结构可见性。它无法回答:这个status字段在业务逻辑中是否等同于order_status表里的status_code?它的合法值集合(0=待支付,1=已支付,9=已取消)有没有被代码硬编码?当某天 DBA 把tinyint改成enum('pending','paid','canceled'),下游服务是否感知?这就是第二层断层:语义一致性缺失。第三层更隐蔽:Excel 字典里写“用户手机号,脱敏存储”,但实际代码里SELECT phone FROM user直接返回明文——文档与实现彻底割裂。这套工具的设计起点,就是用最小侵入方式缝合这三层。
2.2 核心架构:CLI 驱动元数据采集 + YAML 契约定义 + Web 可视化比对
整个流程分三步闭环:
- 采集层(CLI):通过 JDBC/ODBC 连接数据库,提取表名、字段名、类型、长度、是否为空、默认值、索引、外键,但不取注释(因注释常为空或过时);
- 契约层(YAML):开发者手动编写
schema/user.yaml,声明业务语义:tables: - name: user_profile description: "用户主档案,含基础信息与认证状态" fields: - name: id type: bigint description: "全局唯一ID,雪花算法生成" constraints: [primary_key, not_null] - name: phone_encrypted type: varchar(128) description: "AES-256-GCM 加密手机号,密钥由 KMS 管理" constraints: [not_null] business_rules: - "注册时必填,修改需短信验证" - "所有下游服务禁止解密,仅用于模糊匹配" - 比对层(Web):启动
dict-server后,上传最新采集的meta.json与本地schema/*.yaml,系统自动标红三类差异:- ❗结构漂移:数据库有字段
email_verified_at,YAML 未定义; - ⚠️语义漂移:YAML 写
constraints: [not_null],但数据库该字段允许 NULL; - ✅契约吻合:字段存在、类型兼容、约束一致、业务规则被代码注释引用(通过扫描 Java/Python 源码中的
@see user_profile.phone_encrypted)。
- ❗结构漂移:数据库有字段
提示:它不强制要求“所有字段必须有业务描述”,但会对未描述字段打黄标并统计覆盖率。这是务实设计——比起追求 100% 文档化,先守住关键字段的契约底线。
2.3 与主流方案的关键差异:不依赖数据库注释,反向驱动注释生成
对比 Liquibase(专注变更追踪)、SchemaCrawler(纯结构分析)、或自研 SQL 解析器:
- Liquibase 的
changelog是操作日志,不承载业务语义; - SchemaCrawler 输出的 HTML 报告再精美,仍是“快照”,无法回答“这个字段为什么叫
created_by_id而不是creator_id”; - 本工具将 YAML 契约视为唯一真相源(Source of Truth),数据库注释反而由它反向生成:执行
dict-cli sync --to-db时,会把 YAML 中的description自动写入 MySQL 的COMMENT字段(需 DBA 开放ALTER TABLE ... COMMENT权限)。这意味着:文档编辑即生产变更,且所有修改留痕于 Git —— 你看到的不是“谁改了注释”,而是“哪次 commit 引入了对phone_encrypted的密钥管理说明”。
3. 快速上手:三步完成本地验证,10 分钟跑通核心链路
3.1 环境准备:JDK 11+、Python 3.8+、MySQL 5.7+(其他数据库需额外驱动)
# 下载预编译包(Linux x64) wget https://example.com/releases/dict-tool-v2.3.1-linux-amd64.tar.gz tar -xzf dict-tool-v2.3.1-linux-amd64.tar.gz cd dict-tool # 验证 CLI 基础功能 ./dict-cli --version # 输出:dict-cli v2.3.1 (build 20240522) # 初始化配置(生成 config.yaml 模板) ./dict-cli init --db-type mysql --host 127.0.0.1 --port 3306 --database test_db此命令创建config.yaml,关键字段说明:
| 字段 | 示例值 | 说明 |
|---|---|---|
db.username | "dev_user" | 仅需 SELECT 权限,禁止 root |
output.dir | "./output" | 采集结果(meta.json)和契约文件(schema/)存放目录 |
schema.include_tables | ["user_profile", "order_header"] | 白名单模式,避免拉取系统表 |
sync.comment_strategy | "overwrite" | 同步到 DB 时,注释覆盖策略:overwrite(全量)、append(追加)、skip(跳过) |
3.2 第一次采集与契约编写:以user_profile表为例
假设你的 MySQL 中有:
CREATE TABLE user_profile ( id BIGINT PRIMARY KEY AUTO_INCREMENT, nickname VARCHAR(32) NOT NULL, avatar_url VARCHAR(255), created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );执行采集:
./dict-cli collect --config config.yaml # 输出:✅ 已采集 4 张表,元数据保存至 ./output/meta.json此时./output/meta.json包含原始结构,但无业务语义。现在手动创建./schema/user_profile.yaml:
name: user_profile description: "用户昵称与头像信息,不包含敏感身份数据" fields: - name: id type: bigint description: "主键,自增整数" constraints: [primary_key, not_null] - name: nickname type: varchar(32) description: "用户自定义昵称,前端展示用,非唯一" constraints: [not_null] business_rules: - "长度 1-32 字符,禁止空格与特殊符号" - "修改频率限制:每 24 小时最多 1 次" - name: avatar_url type: varchar(255) description: "头像 CDN 地址,格式为 https://cdn.example.com/avatars/{uid}.jpg" constraints: [] business_rules: - "为空时前端显示默认头像" - "URL 必须以 https://cdn.example.com/avatars/ 开头"逻辑说明:YAML 中
constraints: []显式声明“无约束”,区别于缺失该字段(表示未知)。business_rules是数组,方便后续做规则引擎匹配。此处不写created_at字段的业务规则,因它纯属技术字段,契约层可忽略。
3.3 启动 Web 服务并验证差异
# 启动服务(默认端口 8080) ./dict-server --config config.yaml # 浏览器访问 http://localhost:8080 # 上传 ./output/meta.json 和 ./schema/user_profile.yaml页面立即显示比对结果:
id,nickname,avatar_url:✅ 全部吻合;created_at,updated_at:⚠️ 黄标提示“数据库存在但 YAML 未定义,建议补充或确认是否应忽略”;- 点击
nickname字段,右侧展开business_rules并高亮显示:“长度 1-32 字符...” —— 这正是你写的契约。
此时你已获得第一个可验证的数据契约:任何新成员加入,看这个页面就能理解nickname的边界;任何字段变更,CI 流程中运行dict-cli diff即可失败构建。
4. 避坑指南:五个血泪经验换来的高频问题排查清单
4.1 现象:dict-cli collect报错java.sql.SQLException: Access denied for user 'dev_user'@'%'
原因:配置文件中db.username和db.password未正确设置,或数据库用户无SELECT权限。常见误操作是复制了示例配置但忘了改密码,或使用了带特殊字符(如@,$)的密码未做 URL 编码。
解决:
- 检查
config.yaml中密码是否被 YAML 解析器截断(如password: "p@ss$word"应改为password: "p%40ss%24word"); - 手动登录 MySQL 验证权限:
SHOW GRANTS FOR 'dev_user'@'%'; -- 必须包含:GRANT SELECT ON `test_db`.* TO 'dev_user'@'%';
4.2 现象:Web 页面显示created_at字段“类型不匹配”,数据库是DATETIME,YAML 写datetime
原因:YAML 中字段类型必须与数据库驱动返回的 JDBC 类型严格对应,而非随意命名。MySQL 的DATETIME对应 JDBC 类型java.sql.Types.TIMESTAMP,工具内部映射为timestamp。
解决:查阅工具内置类型映射表(docs/type-mapping.md),或执行dict-cli collect --debug查看原始 JDBC 类型:
{ "name": "created_at", "jdbc_type": 93, // 93 = java.sql.Types.TIMESTAMP "type_name": "DATETIME" }将 YAML 中type: datetime改为type: timestamp即可。
4.3 现象:dict-cli sync --to-db执行后,MySQL 表注释未更新
原因:MySQL 8.0+ 默认开启sql_mode=STRICT_TRANS_TABLES,而部分老版本驱动在执行ALTER TABLE ... COMMENT时未正确转义单引号,导致 SQL 语法错误。
解决:
- 在
config.yaml中添加:sync: db_comment_escape: true # 启用注释内容单引号转义 - 或临时降低 SQL 模式(不推荐生产):
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES',''));
4.4 现象:YAML 中写了business_rules,但 Web 页面不显示,或扫描代码时未命中@see注释
原因:business_rules的扫描依赖源码路径配置。工具默认只扫描./src/main/java和./src/main/python,若你的项目结构是./app/models/,则需显式指定。
解决:在config.yaml中配置:
code_scan: paths: ["./app/models", "./app/services"] languages: ["java", "python"]并确保代码中注释格式严格匹配:// @see user_profile.nickname(Java)或# @see user_profile.nickname(Python),中间不能有多余空格。
4.5 现象:多人协作时,schema/*.yaml文件频繁冲突,Git 合并困难
原因:YAML 文件天然不适合行级合并,尤其当多人同时修改同一张表的多个字段时。
解决:采用表级拆分 + 锁定机制:
- 每张表一个独立 YAML 文件(如
user_profile.yaml,order_header.yaml),避免大文件; - 在团队约定中,
schema/目录下新增LOCKED_BY文件,内容为user_profile.yaml: zhangsan@20240525,表示该文件正被张三编辑; - CI 流程中增加检查:
if [ -f "schema/LOCKED_BY" ] && grep -q "user_profile.yaml" schema/LOCKED_BY; then exit 1; fi,防止未解锁就提交。
注意:这不是银弹,但比强行合并 YAML 有效得多。我们团队实践下来,冲突率从每周 3 次降至每月 1 次。
5. 进阶技巧:用 CI/CD 实现“数据契约即代码”,让每一次数据库变更都经过语义审查
5.1 在 GitHub Actions 中嵌入契约校验:让 PR 不通过就无法合入
将数据字典校验作为 PR 检查项,是落地最关键的一步。以下是一个精简可用的.github/workflows/dict-check.yml:
name: Data Dictionary Validation on: pull_request: paths: - 'schema/**' - 'config.yaml' jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup JDK uses: actions/setup-java@v4 with: java-version: '11' distribution: 'temurin' - name: Download dict-tool run: | wget https://example.com/releases/dict-tool-v2.3.1-linux-amd64.tar.gz tar -xzf dict-tool-v2.3.1-linux-amd64.tar.gz - name: Collect current DB schema # 此处连接测试环境数据库,需配置 secrets.DB_URL 等 run: ./dict-tool/dict-cli collect --config config.yaml env: DB_URL: ${{ secrets.DB_URL }} DB_USER: ${{ secrets.DB_USER }} DB_PASS: ${{ secrets.DB_PASS }} - name: Run diff and fail on drift # 关键:--strict 模式下,任何结构或语义漂移都返回非零退出码 run: ./dict-tool/dict-cli diff --config config.yaml --strict - name: Generate HTML report for review if: always() run: ./dict-tool/dict-cli report --format html --output ./report.html # 上传报告供人工复核 - name: Upload artifact uses: actions/upload-artifact@v4 with: name: dict-report path: ./report.html此工作流的核心价值在于:它不阻止你改数据库,但强制你同步更新契约。当某同学在 PR 中删除了user_profile.avatar_url字段,dict-cli diff --strict会立即报错:
❌ Field mismatch in table 'user_profile': - Database has field 'avatar_url' (varchar(255)) - YAML defines no such field → Please update schema/user_profile.yaml or remove the field from DB.PR 检查失败,开发者必须二选一:补全 YAML 描述,或发起数据库变更申请(走 DBA 审批流)。契约从此不再是“可有可无的文档”,而是和单元测试一样硬性的质量门禁。
5.2 用dict-cli export生成多格式交付物:满足不同角色的信息需求
除了 Web 页面,工具支持按角色导出定制化视图:
| 导出命令 | 输出格式 | 适用场景 | 关键参数 |
|---|---|---|---|
dict-cli export --format markdown | Markdown 表格 | 产品需求文档嵌入,轻量易读 | --table-filter user_profile |
dict-cli export --format excel | Excel(.xlsx) | 交付给甲方,支持筛选排序 | --sheet-name "用户域" |
dict-cli export --format openapi | OpenAPI 3.0 Schema | 前端自动生成 TypeScript 接口 | --include-rules false(省略 business_rules) |
dict-cli export --format json-schema | JSON Schema | 用于 Kafka 消息校验或 Airflow DAG 参数验证 | --root-object order_header |
例如,为前端生成User接口定义:
./dict-cli export \ --format openapi \ --schema user_profile \ --output ./openapi/user.yaml \ --include-rules false输出片段:
components: schemas: User: type: object properties: id: type: integer format: int64 nickname: type: string maxLength: 32 avatar_url: type: string maxLength: 255前端运行npx openapi-typescript ./openapi/user.yaml --output src/types/user.ts,即可获得强类型定义。数据契约直接驱动开发,消除口头约定。
5.3 建立“契约健康度”指标:用数字驱动持续改进
在团队周会上,我们不再问“字典写完了吗”,而是看三个数字:
- 覆盖率(Coverage):
YAML 中定义的字段数 / 数据库总字段数 × 100%; - 漂移率(Drift Rate):
上周 diff 发现的漂移项数 / 总检查表数 × 100%; - 引用率(Reference Rate):
代码中@see注释指向 YAML 字段的次数 / YAML 中字段总数 × 100%。
这些数字每天凌晨由定时任务计算并推送到企业微信:
# 每日凌晨 2 点执行 0 2 * * * cd /opt/dict-tool && ./dict-cli health --output json > /var/log/dict-health.json当某天发现漂移率从 0.2% 突增至 5.1%,立刻回溯:原来是 DBA 批量执行了ALTER TABLE ... ADD COLUMN但未通知开发组。我们马上在流程中增加一条规则:所有ALTER TABLE操作,必须先dict-cli collect生成 diff,再由负责人审批 YAML 更新。
从那以后我每次收到 DBA 的变更邮件,第一件事不是点开 SQL,而是打开终端跑dict-cli diff --config config.yaml,确认它和我的本地 YAML 是否一致。如果红标没消失,我就知道这事还没完——契约不是写完就扔的文档,它是数据库每一次心跳的听诊器。希望帮到你。
本文还有配套的精品资源,点击获取