【A11】服务器数据库结构笔记

按当前设计整理。核心 11 表 + 可选 2 表 + 注释 1 表。归属内联(parent_id / owner_id),取消独立归属关系表;通讯录 3 表无主表,依托 resources;created_at 全删(Id 自带时间序)。


一、ID 体系回顾

1.1 编码布局

text 复制代码
i64(64 位):
  bit 63      : 0(符号位,恒 0)
  bit 62      : 0(时间压缩标记,恒 0;为 1 时启用压缩,暂不实现)
  bit 61 ~ 48 : kind(14 位,16384 种)
  bit 47 ~ 0  : time(48 位毫秒,约 8920 年)

1.2 IdKind

kind 值 含义 区分方式
User 0x0000 PANGU + 用户 time == 0 → PANGU;time > 0 → 普通用户
Terminal 0x0001 终端 ---
Resource 0x0002 资源实例 ---
ResourceKind 0x0003 资源类型定义 ---
Group 0x3FFF 组 ---

1.3 PANGU 双重身份

text 复制代码
PANGU 的 ID = 0(kind = User, time = 0)

硬编码部分:
  - 用户名 / 密码常量
  - 应急代码路径
  - 不受数据库删除影响

登录部分:
  - users 表 id = 0 的记录
  - 可走正常登录流程
  - 登录后是普通用户视角

区别只在 time == 0,登录能力 / 权限校验 / 审计与普通用户一致。

1.4 时间语义

  • next():max(now, last+1),接近真实时间
  • add1():纯 +1,只保证顺序,与真实时间漂移

创建时间在 ID 的 48 位 time 里,不需要独立 created_at。


二、主体层

2.1 users(用户)

sql 复制代码
CREATE TABLE users (
    id          INTEGER PRIMARY KEY,   -- Id { kind: User, time }
    id_card     TEXT    NOT NULL UNIQUE, -- 身份证压缩码(属性,非主键)
    name        TEXT    NOT NULL,
    phone       TEXT,
    email       TEXT,
    status      TEXT    NOT NULL DEFAULT 'active'  -- active / left / ...
);

说明:

  • 用户 ID 是时间戳(注册时刻),身份证降为唯一属性
  • 公共表,所有登录者
  • id = 0(PANGU)也在本表,走正常登录流程
  • created_at 删(ID 自带时间序)

2.2 groups(组)

sql 复制代码
CREATE TABLE groups (
    id          INTEGER PRIMARY KEY,   -- Id { kind: Group, time }
    name        TEXT    NOT NULL,
    owner_id    INTEGER NOT NULL      -- 组的事实拥有者(用户)
);

说明:

  • owner_id 是组的事实拥有者(User 类型)
  • 对人:组负责人
  • 对资源:组内资源的事实 owner
  • 组换 owner → 组内资源自动跟随

2.3 terminals(终端 + 资产)

sql 复制代码
CREATE TABLE terminals (
    id              INTEGER PRIMARY KEY,   -- Id { kind: Terminal, time }
    owner_id        INTEGER NOT NULL,      -- 终端拥有人(用户,唯一)
    fingerprint     TEXT    NOT NULL,      -- 终端指纹(综合哈希)
    name            TEXT,

    -- 资产信息(后续扩展,约 30 条)
    mac_address     TEXT,                  -- MAC 地址(指纹原料)
    disk_serial     TEXT,                  -- 硬盘序列号(指纹原料)
    cpu_model       TEXT,                  -- CPU 型号(指纹原料)
    os_version      TEXT,                  -- 操作系统版本
    -- ... 其它资产字段按需补充

    FOREIGN KEY (owner_id) REFERENCES users(id)
);

CREATE INDEX idx_terminals_fingerprint ON terminals(fingerprint);
CREATE INDEX idx_terminals_owner ON terminals(owner_id);

说明:

  • 归属并入本表(owner_id),取消独立 terminal_owner 表
  • 一台终端一个 owner,不会出现第二个
  • 指纹与资产核实统一:指纹匹配 = 关键资产未变
  • mac_address / disk_serial / cpu_model 是指纹原料,也是资产配置

三、资源层

3.1 resource_kind_def(资源类型定义,初版)

sql 复制代码
CREATE TABLE resource_kind_def (
    id           INTEGER PRIMARY KEY,   -- Id { kind: ResourceKind, time }
    name         TEXT    NOT NULL,      -- "通讯录" / "图纸" / "流程"
    decoder      TEXT    NOT NULL,      -- 反序列化器标识(如 "contact_book_v1")
    storage_mode TEXT    NOT NULL,      -- 'table' | 'bytes' | 'external'
    schema       TEXT                   -- 结构定义(JSON,可选)
);

说明:

  • 资源类型是数据,新增插记录,不改代码
  • decoder 是反序列化依据:客户端 / 服务器按此选择解码器
  • 未定稿,先按此实行,有问题调整

反序列化流程:

text 复制代码
resources.resource_kind_id
  → resource_kind_def.decoder
    → 按 decoder 选择反序列化器
      → 例:"contact_book_v1" → ContactBook::decode

3.2 resources(资源实例元信息)

sql 复制代码
CREATE TABLE resources (
    id                INTEGER PRIMARY KEY,   -- Id { kind: Resource, time }
    resource_kind_id  INTEGER NOT NULL,      -- 指向 resource_kind_def
    name              TEXT    NOT NULL,
    parent_id         INTEGER NOT NULL,      -- 唯一拥有者:组 ID 或用户 ID
    content_path      TEXT,                  -- 内容文件路径(为空时数据库内部保存)
    version           INTEGER NOT NULL,      -- 最后修改版本(48 位 time)
    created_by        INTEGER NOT NULL,      -- 创建者(用户)
    FOREIGN KEY (resource_kind_id) REFERENCES resource_kind_def(id)
);

CREATE INDEX idx_resources_kind ON resources(resource_kind_id);
CREATE INDEX idx_resources_parent ON resources(parent_id);

说明:

  • parent_id 是唯一拥有者,kind 决定是组还是用户:
    • parent_id.kind == Group → 资源归组
    • parent_id.kind == User → 资源直接归用户
  • 取消 resource_edges 表,归属直接放 parent_id
  • content_path 为空 → 内容存数据库内部(拆表 / bytes);非空 → 存外部文件
  • version 保留(最后修改时刻),created_by 保留(创建者)
  • created_at 删(ID 自带时间序)

3.3 values(通用字节存储,暂时注释)

sql 复制代码
-- 暂时无需求,注释
-- CREATE TABLE values (
--     resource_id INTEGER PRIMARY KEY,
--     bytes       BLOB    NOT NULL,
--     FOREIGN KEY (resource_id) REFERENCES resources(id)
-- );

说明:

  • 流程、审批、配置:可能用专表,可能外部文件
  • 大文件:用 resources.content_path 指向外部
  • 通用字节:才用 values
  • 资源统一由 resources 管理,存储方式由 resource_kind_def.storage_mode 决定

3.4 通讯录 3 表(无主表)

sql 复制代码
-- 通讯录用户(关联公共 users)
CREATE TABLE contact_users (
    resource_id INTEGER NOT NULL,   -- 通讯录资源
    user_id     INTEGER NOT NULL,   -- 引用公共 users.id
    dept_id     INTEGER,            -- 在该通讯录里的部门(资源内 ID)
    title       TEXT,               -- 在该通讯录里的岗位
    sort_order  INTEGER,
    PRIMARY KEY (resource_id, user_id),
    FOREIGN KEY (resource_id) REFERENCES resources(id),
    FOREIGN KEY (user_id)     REFERENCES users(id)
);

CREATE INDEX idx_contact_users_dept ON contact_users(resource_id, dept_id);
CREATE INDEX idx_contact_users_user ON contact_users(user_id);

-- 通讯录部门(资源内唯一)
CREATE TABLE contact_depts (
    resource_id INTEGER NOT NULL,
    dept_id     INTEGER NOT NULL,   -- 资源内唯一
    name        TEXT    NOT NULL,
    parent_id   INTEGER,            -- 资源内父部门
    sort_order  INTEGER,
    PRIMARY KEY (resource_id, dept_id),
    FOREIGN KEY (resource_id) REFERENCES resources(id)
);

CREATE INDEX idx_contact_depts_parent ON contact_depts(resource_id, parent_id);

-- 通讯录关系(资源内 ID)
CREATE TABLE contact_relations (
    resource_id   INTEGER NOT NULL,
    from_id       INTEGER NOT NULL,   -- 资源内 ID(用户或部门)
    to_id         INTEGER NOT NULL,
    relation_kind TEXT    NOT NULL,   -- 'member' | 'report' | ...
    PRIMARY KEY (resource_id, from_id, to_id, relation_kind),
    FOREIGN KEY (resource_id) REFERENCES resources(id)
);

CREATE INDEX idx_contact_relations_to ON contact_relations(resource_id, to_id);

说明:

  • 无独立 contact_books 主表 ,通讯录元信息在 resources
  • 用户公共 :contact_users.user_id 外键 users.id,不复制用户信息
  • 部门 / 关系按资源隔离 :一张表 + resource_id,不做物理分表
  • 主键都以 resource_id 打头
  • "加入通讯录" = 在 contact_users 插关联,前提是 users 已有该用户

四、关系层

4.1 org_edges(组织结构)

sql 复制代码
CREATE TABLE org_edges (
    from_id    INTEGER NOT NULL,   -- 用户或组
    to_id      INTEGER NOT NULL,   -- 组
    PRIMARY KEY (from_id, to_id)
);

CREATE INDEX idx_org_edges_to ON org_edges(to_id);

说明:

  • edge_kind 去掉,靠 from_id.kind 推断:
    • from_id.kind == User → 用户属于组(membership)
    • from_id.kind == Group → 子组属于父组(hierarchy)
  • created_at 删(边的顺序可由两端 ID 推断)
  • 未来需要"用户对用户"或"组对用户"的边,再考虑加 edge_kind

4.2 terminal_login(终端登录)

sql 复制代码
CREATE TABLE terminal_login (
    terminal_id     INTEGER NOT NULL,
    user_id         INTEGER NOT NULL,
    last_online_at  INTEGER NOT NULL,   -- 最后在线时刻
    status          TEXT    NOT NULL DEFAULT 'offline',  -- 'online' | 'offline'
    PRIMARY KEY (terminal_id, user_id)
);

CREATE INDEX idx_terminal_login_status ON terminal_login(status, last_online_at);

说明:

  • 用户 → 终端,登录状态 + 最后在线时间
  • 保留,不并入 terminals:
    • terminals:终端归属(一台一个 owner)
    • terminal_login:登录记录(一台终端多人可登录)
  • last_online_at 保留(动态时间,非创建时间)
  • 心跳 64×1024 ms ≈ 65.5 秒,窗口 1024×1024 ms ≈ 17.5 分钟

五、权限层

5.1 grants(组级权限)

sql 复制代码
CREATE TABLE grants (
    group_id   INTEGER NOT NULL,
    pc_id      INTEGER NOT NULL,   -- 终端 ID
    can_read   BOOLEAN NOT NULL DEFAULT 0,
    can_write  BOOLEAN NOT NULL DEFAULT 0,
    PRIMARY KEY (group_id, pc_id)
);

CREATE INDEX idx_grants_pc ON grants(pc_id);

说明:

  • 授权单位是组,组内资源继承组权限
  • granted_at 删(授权时刻由 audit_log 承载)
  • 客户端权限表是此表的按 pc_id 过滤子集

六、辅助层

6.1 audit_log(审计)

sql 复制代码
CREATE TABLE audit_log (
    id          INTEGER PRIMARY KEY AUTOINCREMENT,
    at          INTEGER NOT NULL,   -- 操作时刻(必须保留)
    actor       INTEGER NOT NULL,   -- 操作人
    op          TEXT    NOT NULL,   -- insert / update / delete / transfer
    target      INTEGER NOT NULL,   -- 目标资源
    detail      TEXT,               -- 差异 / 说明
    source      TEXT                -- 来源(流程单号等,可选)
);

CREATE INDEX idx_audit_at ON audit_log(at);
CREATE INDEX idx_audit_target ON audit_log(target);

说明:

  • append-only,不可改
  • at 必须保留(操作时刻,非创建时刻)
  • ID 是自增,不是 Id

6.2 transfer_chain(接替链)

sql 复制代码
CREATE TABLE transfer_chain (
    resource_id INTEGER NOT NULL,
    seq         INTEGER NOT NULL,
    from_id     INTEGER NOT NULL,
    to_id       INTEGER NOT NULL,
    at          INTEGER NOT NULL,   -- 移交时刻(必须保留)
    reason      TEXT,
    PRIMARY KEY (resource_id, seq)
);

说明:

  • 资源所有权移交历史,链首是 PANGU
  • at 必须保留(业务事件时间)

6.3 blocks(块,可选)

sql 复制代码
-- 增量同步用,全量同步时可省略
CREATE TABLE blocks (
    id          INTEGER PRIMARY KEY,   -- 块起点
    end_time    INTEGER NOT NULL,      -- 块终点
    resource_id INTEGER NOT NULL,      -- 所属资源
    changes     BLOB    NOT NULL,      -- 净变化(JSON / bincode)
    FOREIGN KEY (resource_id) REFERENCES resources(id)
);

CREATE INDEX idx_blocks_resource ON blocks(resource_id, end_time);

6.4 history_resources(历史,可选)

sql 复制代码
-- 全量上传时旧数据入历史
CREATE TABLE history_resources (
    resource_id  INTEGER NOT NULL,
    version      INTEGER NOT NULL,   -- 旧版本
    bytes        BLOB    NOT NULL,   -- 旧数据
    archived_at  INTEGER NOT NULL,   -- 归档时刻(必须保留)
    PRIMARY KEY (resource_id, version)
);

七、表清单汇总

层 表 状态 说明
主体 users ✅ 用户(含 PANGU),身份证是属性
主体 groups ✅ 组,owner_id 是事实拥有者
主体 terminals ✅ 终端 + 资产 + owner_id
资源 resource_kind_def ✅ 类型定义,decoder 是反序列化依据
资源 resources ✅ 实例元信息,parent_id 唯一拥有者
资源 values ⏸️ 注释 暂无需求
资源 contact_users ✅ 通讯录用户(关联公共 users)
资源 contact_depts ✅ 通讯录部门(资源内唯一)
资源 contact_relations ✅ 通讯录关系(资源内 ID)
关系 org_edges ✅ 组织结构,edge_kind 由 from_id.kind 推断
关系 terminal_login ✅ 终端登录
权限 grants ✅ 组级权限
辅助 audit_log ✅ 审计
辅助 transfer_chain ✅ 接替链
辅助 blocks ⚠️ 可选 增量同步
辅助 history_resources ⚠️ 可选 历史版本

核心 11 表 + 可选 2 表 + 注释 1 表。


八、关键设计决策

8.1 归属内联

text 复制代码
resources.parent_id  → 组或用户
terminals.owner_id   → 用户
groups.owner_id      → 用户

取消 resource_edges / terminal_owner 表。
唯一拥有者用字段表达,不需要关系表。

8.2 通讯录无主表

text 复制代码
resources 承载通讯录元信息(id / name / kind)
contact_users / contact_depts / contact_relations 存具体数据
3 表通过 resource_id 关联 resources

8.3 时间字段取舍

类型 处理
创建时间 删(ID 自带)
事件时间(audit_log.at / transfer_chain.at) 保留
动态时间(terminal_login.last_online_at) 保留
最后修改版本(resources.version) 保留
创建者(resources.created_by) 保留
归档时刻(history_resources.archived_at) 保留

8.4 关系表精简

text 复制代码
org_edges:去掉 edge_kind,靠 from_id.kind 推断
terminal_login:保留(登录是多人多终端的关系,与归属不同)

8.5 用户公共

text 复制代码
users:公共表,所有登录者(含 PANGU)
contact_users:关联表,不复制用户信息
展示时 JOIN

8.6 部门/关系按资源隔离

text 复制代码
contact_depts / contact_relations:一张表 + resource_id
不做物理分表(表数量爆炸、DDL 复杂、跨资源查询难)
主键以 resource_id 打头

8.7 PANGU 双重身份

text 复制代码
硬编码:用户名 / 密码常量、应急代码路径、不受数据库删除影响
登录:users 表 id = 0,可走正常登录流程
区别:只在 time == 0

九、数据流示例

9.1 读通讯录

text 复制代码
pc 请求资源 R:
  1. resources[R] → parent_id = G
  2. G.kind == Group → groups[G].owner_id = A
  3. grants[G][pc] → can_read?
  4. can_read → 从 contact_* 表组装
  5. 返回

9.2 写通讯录

text 复制代码
pc 提交全量通讯录:
  1. resources[R] → parent_id = G
  2. grants[G][pc] → can_write?
  3. 解析 JSON → 3 个 Vec
  4. 清空 + 重插 contact_*
  5. 更新 resources.version

9.3 终端归属解析

text 复制代码
资源 R 的事实 owner:
  1. resources[R].parent_id = P
  2. P.kind == Group → groups[P].owner_id = A
  3. P.kind == User → A = P
  4. A 是用户 → 终点

pc 是 R 的 owner 终端?
  1. terminals[pc].owner_id = A
  2. A == R 的事实 owner → 是

9.4 终端指纹校验

text 复制代码
pc 登录 / 心跳:
  1. terminals[pc].fingerprint == 客户端上报的指纹?
  2. 匹配 → 允许
  3. 不匹配 → 拒绝(终端可能被替换)

9.5 PANGU 登录

text 复制代码
PANGU 登录:
  1. 客户端提交 admin / admin11(或改后的密码)
  2. 走正常登录流程 → users[id = 0]
  3. 登录成功,获得普通用户 token
  4. 硬编码部分(应急代码)另行触发,与登录独立

十、一句话

服务器 11 张核心表:主体 3(users/groups/terminals)、资源 5(resource_kind_def/resources/contact_*)、关系 2(org_edges/terminal_login)、权限 1(grants)+ 辅助(audit_log/transfer_chain)+ 可选(blocks/history_resources)。归属内联(parent_id / owner_id),通讯录无主表,created_at 全删,edge_kind 去掉。Human / Device 统一改为 User / Terminal,PANGU 可登录。

归属内联,关系精简。用户公共,部门/关系按资源隔离。时间在 ID 里,事件在字段里。PANGU 能登录,time=0 是唯一区别。

相关推荐
企业解惑小能手-域智盾系统1 小时前
终端安全管理软件怎么选?终端安全管理不是“装个客户端”:从底层逻辑看企业怎么选
服务器·网络·安全·域智盾软件
Dxy12393102161 小时前
Linux 服务器 vi 命令怎么使用
linux·运维·服务器
叼烟扛炮1 小时前
Linux 学习笔记(十五):进程的魔法 fork 与 僵尸孤儿
linux·运维·服务器
isNotNullX1 小时前
智能问数技术路线怎么选?从Text-to-SQL到Data Agent一次讲清
数据库·oracle
钝挫力PROGRAMER1 小时前
从“硬件报错”到“内核崩溃”:一次超微(Supermicro)服务器失联问题解决记录
服务器·内核升级·无法连接
鸽芷咕1 小时前
换库不申请停机窗口?金仓KFS数据集成软件双轨并行,还真行
数据库
1314lay_10071 小时前
ABAP 读取服务器的文件 OPEN DATASET,READ DATASET f_filepath INTO l_file.
经验分享·笔记
鸽芷咕1 小时前
月底报表又把库拖垮了?聊聊金仓数据库KES的列存储和真本事
数据库
Juicedata1 小时前
面向 EB 级 AI 存储:JuiceFS 企业版架构演进
数据库·人工智能·架构