4.9 数据库设计
概述
25 张业务表、统一审计列、13 个唯一索引、9 张租户级表、注释枚举驱动字典——本节给出数据模型全景与 ER 关系。五方言定稿脚本位于 document/{mysql,postgresql,sqlserver,oracle,sqlite}/,MySQL 版为规范基准。
ER 关系图(逻辑外键,无物理外键约束)
text
goframe_tenant ──< goframe_user >──┬──< goframe_user_role >── goframe_role
│ │
│ goframe_role_menu
│ │
├──< goframe_dept ▼
├──< goframe_level goframe_menu
├──< goframe_position ▲
│ (user.level_id/position_id/dept_id 引用)
│
goframe_config ──< goframe_config_item
goframe_dict ──< goframe_dict_item
goframe_category(树 parent_id) ──< goframe_article(tenant_id, category_id)
article: cover 单图 / images 多图 / content 富文本
goframe_notice / goframe_link(tenant_id)
goframe_city(树 pid + parent_code,全国行政区划,无租户)
goframe_job ──< goframe_job_log(job_id, job_name 冗余)
goframe_operation_log / goframe_login_log(独立日志表,无租户)
goframe_file_template(全局文件模板,code 唯一)
goframe_param(全局系统参数,code 唯一)
goframe_example(案例演示表,导入导出/状态演示用)
">" 侧为多端;如 user >-- user_role --< role 为多对多。全表统一规范
text
表前缀 goframe_;存储引擎 InnoDB;字符集 utf8mb4。
每张表统一审计列(25 表齐备):
id int NOT NULL AUTO_INCREMENT 主键(数据库自增,禁用雪花)
create_user varchar(50) 创建人(ctx 用户名)
create_time datetime DEFAULT (now()) 创建时间
update_user varchar(50) 更新人
update_time datetime DEFAULT (now()) 更新时间
del_flag int DEFAULT 0 0-正常 1-已删除(软删)
租户级表另有 tenant_id int DEFAULT 0(0=平台级),共 9 张。
删除一律软删(deleteHook 改写);查询一律经 dao.Ctx 过滤 del_flag=0。25 张表清单
| 表名 | 中文注释 | 域 | 租户级 | 特征列/说明 |
|---|---|---|---|---|
| goframe_article | 文章表 | content | 是 | category_id/cover/images(多图)/content(富文本)/status/click/sort |
| goframe_category | 文章分类表 | content | 是 | 树形 parent_id、category_name/code/sort |
| goframe_city | 城市行政区划表 | data | 否 | 树形 pid+parent_code、city_code/area_code/level、lng/lat/pinyin(大数据量表) |
| goframe_config | 系统配置表 | data | 否 | name/code/sort |
| goframe_config_item | 配置项表 | data | 否 | config_id/value/options/type/status/sort |
| goframe_dept | 部门表 | system | 是 | 树形、删除有子级/用户守卫 |
| goframe_dict | 数据字典表 | data | 否 | name/code;缓存 dict:item:{code} |
| goframe_dict_item | 字典项表 | data | 否 | dict_id/name/value/sort |
| goframe_example | 案例演示表 | tool | 否 | 七件套+导入导出+状态演示 |
| goframe_file_template | 文件模板表 | tool | 否 | code 唯一;getTemplateByCode |
| goframe_job | 定时任务表 | monitor | 否 | job_name/cron_expression/execute_policy/is_sync/url/params/status(0未发布/1运行/2暂停) |
| goframe_job_log | 定时任务日志表 | monitor | 否 | job_id/status/耗时/exception_info |
| goframe_level | 职级表 | system | 是 | 导入导出启用;user_count 展示 |
| goframe_link | 友链表 | content | 是 | 无 status 列 |
| goframe_login_log | 登录日志表 | monitor | 否 | log_type(1登录/2退出)/ip/location/os/browser/status |
| goframe_menu | 菜单表 | system | 否 | 树形;type(0菜单/1权限节点)/permission/status/hide/sort |
| goframe_notice | 通知公告表 | data | 是 | status |
| goframe_operation_log | 操作日志表 | monitor | 否 | title/type(log_type枚举)/param/result/ip/location/consume_time/status/error |
| goframe_param | 系统参数表 | data | 否 | code 唯一 |
| goframe_position | 岗位表 | system | 是 | |
| goframe_role | 角色表 | system | 是 | code/data_scope(四档行级数据权限) |
| goframe_role_menu | 角色菜单关联表 | system | 否 | role_id+menu_id(无模块文件,归 role logic) |
| goframe_tenant | 租户表 | system | 否 | code(T+ID)/status/expire_time/max_user_num |
| goframe_user | 用户表 | system | 是 | username/password(bcrypt)/salt/mobile/email/avatar/dept_id/level_id/position_id/status/code |
| goframe_user_role | 用户角色关联表 | system | 否 | user_id+role_id(无模块文件,归 user logic) |
唯一索引清单(13 个)
| 表 | 索引名 | 列 | 语义 |
|---|---|---|---|
| goframe_category | uk_tenant_name | (tenant_id, category_name, del_flag) | 租户内分类名唯一 |
| goframe_config | uk_code | (code) | 全局配置编码唯一 |
| goframe_dept | uk_tenant_name | (tenant_id, name, del_flag) | 租户内部门名唯一 |
| goframe_dict | uk_code | (code) | 全局字典编码唯一 |
| goframe_file_template | uk_code | (code) | 全局模板编码唯一 |
| goframe_level | uk_tenant_name | (tenant_id, name, del_flag) | 租户内职级名唯一 |
| goframe_param | uk_code | (code) | 全局参数编码唯一 |
| goframe_position | uk_tenant_name | (tenant_id, name, del_flag) | 租户内岗位名唯一 |
| goframe_role | uk_tenant_code | (tenant_id, code, del_flag) | 租户内角色编码唯一 |
| goframe_tenant | uk_code | (code) | 租户编码全局唯一 |
| goframe_user | uk_tenant_username | (tenant_id, username, del_flag) | 租户内用户名唯一 |
| goframe_user | uk_tenant_mobile | (tenant_id, mobile, del_flag) | 租户内手机号唯一 |
| goframe_user | uk_tenant_code | (tenant_id, code, del_flag) | 租户内用户编码唯一 |
要点:索引含 del_flag(软删行不占坑,与 dao.Ctx 恒过滤语义一致);含 tenant_id 的索引,模块唯一预检范围必须等于索引范围。
枚举列约定(列注释驱动字典与生成器)
text
status(账号/租户/字典项等) 1-正常 2-禁用
article.status 0-正常 1-下架
city.level 0-省份 1-城市 2-县区 3-街道 4-社区
menu.type 0-菜单 1-权限节点
job.status 0-未发布 1-运行中 2-暂停
job.execute_policy 1-立即执行 2-执行一次 3-放弃执行
job.is_sync 1-同步 0-异步
role.data_scope 1-全部 2-本部门及以下 3-本部门 4-仅本人
del_flag 0-正常 1-已删除
login_log.log_type 1-登录 2-退出
operation_log.type 见 consts/log_type.go(41 个值,静态映射不走字典)大表与性能注意
- goframe_city 全国行政区划大表(AUTO_INCREMENT 已至 78 万+):查询走 parent_code/pid 索引路径(级联懒加载 getCityList),避免全表 List;导入/迁移注意批大小。
- 日志三表(operation_log/login_log/job_log)只增不改,依赖 LogClean 任务按
job.logRetentionDays(默认 90 天)分批物理清理。 - 导出接口统一 ChunkQuery 分批(500/页)防 OOM。
建表/变更工作流
text
1) 以 document/mysql/ 定稿为基准补 ALTER(含列注释枚举、uk_* 唯一索引、uk_/idx_ 命名规范)
2) gf gen dao -c hack/config.yaml 刷新 dao/entity/do(service 手维护)
3) 同步 document/ 其余四方言脚本(人工校对)
4) 租户级表 → 修改 hooks.tenantTables
5) go build ./... 重启;必要时 go run ./cmd/migrator 同步到其他环境库