Files
ai_site/松离线-dbsync方案.md
whm 76cdcd760e feat: ship loose-offline dbsync (validate, agent push, LWW audit)
Add UUID/FK channel checks, agent whitelist/push APIs, bindings, super-admin LWW audit with rollback, reconcile rate limits, and sync docs. Default customers stay opt-in; company conflict UI is removed.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-31 17:54:14 +08:00

30 KiB
Raw Permalink Blame History

方案稿:松离线 + 接法①dbsync

状态:已冻结 → 请以 松离线-dbsync方案-最终版.md 为准开工
本文保留为过程稿(正文草稿 + 双方审评 + 协商记录),口径以最终版为准
日期2026-07-31
配套:智建修改意见.mddocs/数据同步-中间件.md、宇恒 db_write_gateway.py


1. 一句话

离线在本地正式库按最终 UUID 落库;联网靠 dbsync 通道把本地 B 与线上 A 同主键幂等对齐。
不做 HTTP 双写主路径;不做「两端自增再对账」。


2. 角色与库

角色 说明
A 智建线上主库 Postgres租户/应用库)
B 宇恒本机正式库 SQLite permanent按用户绑定的 local_database_id
绑定 (tenant_id, user_id, local_database_id) → online_db_id 宇恒本地登记;智建侧可查询/登记同一映射,通道 remote 指向对应 A

通道(管理员配置,或安装时模板下发):

local  = Bsqlite该用户库文件
remote = A该 online_db_id / 租户库 DSN
方向   = bidirectional或先 B→A稳定后再双向
冲突   = LWW自动+ 超级管理员可查覆盖日志;非用户 queue
表白名单 = 仅 UUID 主键业务表
业务写 ──► B本地正式库带 UUID
              │
              ├─ 触发器 → _ajz_sync_outbox → worker → A同 PK upsert
              │
              └─ A 上变更 ←── outbox 拉回 ── B双向时
对账兜底reconcile主键集合差+ conflicts 队列

3. 松离线语义(写路径)

场景 行为
离线写 客户端生成 UUID → 直接写 B 正式表 → 成功即对用户可见;同时可标 sync_status=pending(可选列)
联网写 同样写 B带 UUID触发器进 outbox近实时推 A
不做 离线只写 pending、正式表空着那是紧离线本方案不用
不做 业务主路径先 HTTP 打智建 permanent 再 mirror接法②本方案不用

Insert 约定:

  1. 请求/落库行必须带 idUUID,客户端生成。
  2. 禁止依赖 INTEGER AUTOINCREMENT 当同步键。
  3. 重复提交同一 id → upsert / 忽略,不多行。

4. 表结构约定A/B 同步表白名单)

要求
主键 id TEXTUUID 字符串)
建议列 updated_atversion(配合 LWW / 版本跳过)
可选列 sync_statussynced / pending / conflict)仅 UI同步仍靠 outbox
存量自增表 不进白名单,或先迁移 UUID 再进
通道 pk_columns 默认 id;复合主键显式配置

5. 两端职责

宇恒客户端

做什么
UUID insert 前生成并写入update/delete 带同一 id
写路径 apply_write始终先写本地 B(松);去掉「离线只 pending 不落库」
联网 不依赖 HTTP 双写;确保本机 B 上 dbsync 触发器/ agent 可用,或由智建侧连 B 的方式落地(见下「通道落地形态」)
绑定 保留 BindingStore;启动时向智建登记/校验 online_db_id
UI 可显示「待同步」;不展示冲突处理;以本地正式数据为离线真相

智建平台

做什么
dbsync 通道、outbox、ingest、reconcile、conflicts — 复用现有
表规范 控制台/文档写死:同步表必须 UUID 主键
绑定 API 提供「登记/查询 online_db_id ↔ 租户库」供宇恒对齐P1
对账入口 管理员 sync API 已有可选网关代调给终端用户「一键对账」P1
线上业务写 控制台/网页改 A 时同样走带 UUID 的写;触发器推回 B

6. 通道落地形态:已选定 B本机 sync agent

dbsync worker 默认跑在智建 platform 上时,往往连不到用户电脑上的 SQLite B。选定

形态 B已定

用户电脑:业务写 B → 本机 sync agent触发器 / outbox→ 推到线上 A
                                              ← 拉取 A 变更回 B双向时
智建平台:提供线上 A、鉴权、对账/冲突 API、通道元数据不直连用户 SQLite
约定
agent 位置 宇恒本机(独立进程或嵌入客户端)
推送目标 智建线上库 Aonline_db_id / 租户库)
平台职责 A 侧接收(兼容现有 ingest/应用逻辑、conflicts、reconcile 入口
为何不选 A 用户电脑公网不可达,平台无法直连 B
为何不选 C C 仅作过渡;主路径要近实时 outbox用 B

曾对比(归档)

形态 说明 结论
A. 智建连远程 B 平台 DSN 直连用户库 否(公网不可达)
B. 本机 sync agent 本机推/拉 A 采用
C. 批量 ingest 过渡 联网后打包推 仅应急,非主路径

7. 与当前实现的差异(改造清单)

现状 本方案目标
宇恒 online_primary:离线 pending、不写正式库 离线 写正式库UUID
宇恒联网HTTP 先写线上再 mirror 联网 写本地 B,由 dbsync 推 A
智建 dbsync 偏管理员控制台 增加绑定对齐 +(可选)用户侧对账入口
业务表可能自增主键 同步表白名单强制 UUID

建议改造顺序:

  1. 规范:同步表 UUID + 建表模板(智建 + 宇恒)
  2. 宇恒写路径:松离线落 B + 强制 id
  3. 本机 agent:按形态 B 打通一条演示通道(本机 outbox → A
  4. 绑定 APIonline_db_id 可查可登记
  5. 对账 + LWW 覆盖日志reconcile 沿用LWW 落败快照仅超级管理员可查
  6. 下线接法②主路径HTTP 双写仅作运维/兼容开关)

8. 数据流示例

离线插入

用户点保存
  → 客户端 uuid = U1
  → INSERT INTO B.orders (id=U1, ...)   ✅ 本地立刻可见
  → outbox 暂存本地(触发器);无法推 A
联网后
  → worker/agent 投递 Aupsert id=U1
  → A、B 同主键sync_status=synced若有

联网插入

→ 写 B (id=U2) → outbox → 秒级 upsert A

冲突

离线改 U1同时线上也改 U1
  → LWW 自动留一版,另一版写入「自动覆盖日志」(含两边 payload
  → 终端用户无感;仅平台超级管理员可查/导出(可选回滚)
  → 禁止换新主键重试

漏数兜底

POST reconcile → 按主键集合补缺 → 不多发号

9. 验收标准

  • 离线插入(客户端 UUID→ 本地立刻有行;联网后 A 与 B 同一 id,无第二行。
  • 同一 UUID 重复写 / 重放 outbox → 幂等
  • 断网窗口结束 + 对账后,白名单表主键集合无持续缺口。
  • 同 PK 并发 → LWW 自动覆盖,不改主键;落败方在超级管理员覆盖日志中可查。
  • 自增旧表未进白名单,误配会被拒绝或文档明确排除。
  • 关闭 HTTP 双写主开关后,业务仍仅靠 B + dbsync 对齐。

10. 明确不做

  • 紧离线(只 pending、正式表不落作为本方案主路径。
  • 接法② HTTP 双写作为主同步。
  • 两端自增 + 事后映射。
  • 回放/投递失败时换新 UUID 重试。

11. 评审结论

结论
离线模型 松离线(本地正式库落 UUID
同步接法 ① dbsync
通道形态 B 本机 sync agent
冲突默认 LWW自动裁决终端用户零操作;建议按 updated_at/version,单客户端场景可偏本机(lww_source
覆盖可追溯 LWW 仍自动覆盖,但必须写「自动覆盖日志」(见下)
谁可查日志 仅平台超级管理员(非公司 top / 租户管理员)
兼容开关 过渡期保留 online_primaryHTTP 双写),灰度后再切默认

自动覆盖日志(相对现网 dbsync 的补强)

现网纯 LWW 不会把落败方写入 conflicts.json。本方案要求:

约定
何时写 每次因版本较旧而跳过(lww_target)或因 LWW 覆盖目标旧行(lww_source
记什么 tenant_id、通道、表、row_pk、源/目标 version、两边 payload 快照、胜出策略、时间
存储 独立审计(如 data/dbsync/lww_audit.json 或平台审计表),不要当成用户待办冲突队列
终端用户 无入口、无提示、不阻断同步
公司 top 不可见(与现「数据同步」控制台租户管理员权限分离)
平台超级管理员 可查、可导出可选「按快照回滚某一行」P2

权限口径:

公司 top租户管理员→ 配自己公司的通道 / 对账(沿用现权限)
平台超级管理员     → 看全局 LWW 自动覆盖日志 / 应急回滚
终端用户           → 不参与冲突处理

12. 一句话验收口径

松离线写 B最终 UUID+ 本机 agent 走 dbsync冲突自动 LWW落败方进超级管理员可查的覆盖日志主键不漂。


宇恒追加-审评意见

说明:本节是宇恒侧对上文方案的外部审评意见,不是方案正文的修订稿。采纳与否单独决议;未并入 §1§12。
硬约束(宇恒侧)这边的修改不得影响原有用户操作与现网写库逻辑——默认行为保持现状;新能力仅 opt-in / 白名单生效。

A. 总评

方案主线(松离线写 B + UUID + 本机 agent + dbsync + LWW与「离线可用且联网后主键不漂」目标匹配可立。
但在宇恒落地时必须遵守:

原则 含义
默认不变 未开新模式时,等同现网:local_only 或现有 online_primary 行为与契约不变
显式开启 YXD_SYNC_MODE=local_dbsync(名可再定)+ 同步表白名单 时走松离线/dbsync
白名单隔离 未进白名单的表:仍可自增、仍走原 insert禁止因全库切 UUID/强制 id 拖垮旧插件
双路径互斥 同一库/表不得同时 HTTP 双写与 local_dbsync避免双写放大
可回滚 关开关即回到原行为,无需迁数据才能用旧功能

因此:正文目标可做,但宇恒改造必须是「旁路增量」,不是改默认写路径。

B. 同意保留的决策(在不影响原有的前提下)

意见
不做接法②作主路径 同意;现网 online_primary 可作兼容保留,默认可不切走
形态 B 本机 agent 同意;仅对已开通同步的用户/库启用
终端零冲突 UI 同意;且未开通同步的用户完全无感(无新状态条、无强制 agent
过渡期保留 HTTP 开关 同意;默认勿切 local_dbsync

C. 建议补强(保证「不影响原有」)

  1. 模式三分,默认旧行为

    • local_only:只写本地(现网兼容默认之一)
    • online_primary:现网 HTTP 双写(已上线客户可继续)
    • local_dbsync松离线 + agent仅显式配置
      未配置 / 未识别 → 不得自动升到 local_dbsync
  2. 强制 UUID / 必带 id 仅白名单表
    网关:白名单表缺 id 可补 UUID 或 400非白名单表保持原样(允许自增、允许不传 id
    禁止「全局 create_table 改成 UUID」一刀切——可新增「同步表模板」旧模板不动。

  3. apply_write 分支,不改旧分支语义

    • local_only / online_primary:代码路径与响应字段兼容现网(可多字段,不可少成功语义)
    • local_dbsync:才「始终写 B、不依赖离线 pending 空正式表」
      旧调用方继续认 success;勿要求全员改认 pending
  4. agent 可选装
    未装 agent / 未开通同步:业务写库与现网一致;禁止写前强依赖 agent 心跳导致保存失败。
    「仅本机 / 待同步 / 已同步」仅对白名单且已开通同步的会话展示。

  5. 外键 / 闭包
    仅约束「要进同步白名单」的表集;未同步的旧关联表不强制改造。

  6. 删改幂等、安全、对账
    仍建议做,但范围限 local_dbsync + 白名单;不影响未开通路径。

  7. 建表模板
    双端「同步表模板」新增;默认建表模板保持自增,避免新用户无感被切 UUID。

  8. 联网 reconcile
    仅同步用户;设置页入口可选;默认不弹、不阻断。

D. 对现有用户操作逻辑的影响(按约束重述)

对象 要求结果
未开 local_dbsync 的用户 零影响:保存/查询/自增表/插件与现网一致
未进白名单的表 零影响:不强制 UUID、不强制 agent
已开同步的白名单表 预期内变更:离线立刻落 B、带 UUID、可显示待同步
聊天 / 选站 / 税务等非 permanent 同步写路径 零影响

若某改造会导致「未开同步也改变保存结果」→ 不予合入,改回 opt-in。

E. 建议验收追加项(含「不影响原有」)

  • 默认配置下跑现网回归insert 不传 id 的自增表、offline pending 若仍开 online_primary)与改前一致。
  • 仅打开 local_dbsync + 白名单后:松离线 UUID 验收§9通过。
  • agent 停运:未开通用户保存仍成功;开通用户本地可写且待同步,恢复后主键不双行。
  • 网页与客户端双入口仅同步表LWW 符合偏向;超管日志可查。
  • 非白名单表加入通道:拒绝或警告。
  • local_dbsynconline_primary 互斥;关 local_dbsync 后行为回到原模式。

F. 不建议纳入本方案(避免范围膨胀与误伤)

  • 用对账替换 UUID 主键策略。
  • 终端用户冲突工作台。
  • 平台直连用户 SQLite形态 A
  • 默认全局改主键 / 默认切 local_dbsync / 强制全员装 agent。

G. 一句话评审口径

方案可立,但宇恒必须旁路增量:默认不影响原有;仅白名单 + 显式 local_dbsync 走松离线。先灰度开通,再谈切默认。


智建追加-审评意见

说明:本节是智建/方案侧对正文及「宇恒追加-审评意见」的复核意见,不是方案正文修订稿。与宇恒追加并列,采纳单独决议。

A. 总评

同意宇恒总评:主线可立,必须白名单灰度,不可默认切全库。
智建侧补充:现网 dbsyncoutbox / ingest / reconcile / LWW够用当引擎缺口在 本机 agent 协议面LWW 覆盖审计(超管)绑定 API,不是再造同步中间件。
与宇恒追加 无方向冲突;下文对 C 条逐项表态,便于开工排序。

B. 同意保留 / 同意宇恒已同意项

意见
松离线 + ① + 形态 B + LWW + 超管覆盖日志 维持正文定案
不做接法②主路径 / 不做形态 A / 终端零冲突 UI 同意(与宇恒 B 节一致)
过渡期保留 online_primary 同意;切默认前须互斥,禁止双路径同时写
白名单灰度 同意并升为 P0 开工前提

C. 对「宇恒追加 · C 建议补强」的表态

# 宇恒建议 智建意见 建议处置
1 外键 / 同步闭包 同意 写入规范:白名单按闭包进;跨名单外键配置期拒绝
2 agent 未就绪与「立刻可见」 同意 UI 三态(仅本机/待同步/已同步)+ 写前/写后可探测 agent 心跳;属宇恒 P0
3 双入口吞改 同意偏保守 双入口表:先 B→A稳定后再双向LWW 默认可偏本机,但双入口表在超管日志外可加「弱提示已自动合并」(仍不选边)
4 delete / 重放顺序 同意 正文补:墓碑或 outbox deleteagent 按 outbox id 保序;禁止失败换新 UUID
5 YXD_SYNC_MODE=local_dbsync 同意 三分:local_only / online_primary / local_dbsync;文档与发版说明同步
6 双端建表模板 同意P0 智建 create + 宇恒 create 同时改;入通道校验非 TEXT UUID PK → 拒绝
7 agent 凭证与 outbox 敏感列 同意 正文加安全节:最小权限、按 online_db_id 隔离、可吊销outbox 敏感列加密或脱敏 at rest
8 联网自动 reconcile 同意 限流自动对账 + 设置页「同步修复」;暴露 conflicts 给终端;公司 top 仍可走现控制台

D. 智建侧另补(宇恒未写或平台专属)

  1. LWW 审计权限
    维持:仅平台超级管理员;与公司 top「数据同步」菜单分离。实现上独立 API/页,勿挂在租户 sync 控制台下以免误授权。

  2. A 侧接收面
    agent 推送优先复用/扩展现有 ingest或等价 upsert 接口),保证 认客户端 UUID、幂等;避免再开一套与 dbsync 语义不一致的 HTTP 写。

  3. 时钟与 version
    LWW 依赖 updated_at/version:约定客户端单调时钟或服务端授时规则,防止对时错误导致「旧盖新」。建议 version 用 outbox 单调序号为主、时间戳为辅。

  4. 超管日志保留策略
    覆盖日志需 TTL/容量上限(如 90 天或按租户配额),避免无限涨;导出权限同超管。

E. 对现有用户操作逻辑的影响(复核)

对象 影响程度 说明
终端(白名单表) 中高 同意宇恒:契约带 UUID + 可见性语义变化;用白名单限面
终端冲突 降低 同意;无选边
自增插件/脚本 高(仅误入白名单时) 配置期拒绝可把风险压到「零误配」
「保存后线上立刻读到」 同意改为异步需延迟可观测agent 状态)
公司 top 低~中 多「闭包校验 / 单向先」配置纪律;仍无 LWW 审计
平台超管 新增 覆盖日志查询/导出P2按快照回滚

结论:同意宇恒「冲击面用白名单隔离」;智建把住 入通道校验 + 超管审计隔离 + ingest 幂等 三条,终端无感冲突可成立。

F. 建议验收追加项(相对 §9 与宇恒 E

  • 采纳宇恒 E 全部四条agent 停运、双入口 LWW、非白名单拒绝、模式互斥
  • 超管可按 tenant_id / 表 / row_pk 检索覆盖日志,且公司 top Token 403
  • 白名单闭包:只配父表不配子表时,保存通道失败并给出明确错误。
  • local_dbsync 下业务写不调用 permanent HTTP 双写主路径(开关关闭时无双写流量)。

G. 不建议纳入本方案

  • 同意宇恒 F不对账替代 UUID、不做终端冲突台、不做形态 A。
  • 另:不做字段级自动合并CRDT 作本期范围;需要时另立专项。
  • 不把 LWW 审计对租户管理员开放(即使只读),避免与「超管」口径混淆。

H. 一句话评审口径

同意宇恒「可立、先白名单再切默认」;正文方向不改。开工顺序建议:双端 UUID 模板与入通道校验 → local_dbsync 松离线写 B → agent 最小推送 + 超管 LWW 日志 → 再灰度关 HTTP 双写。


协商决议版(双方意见合成 · 以此为准开工)

效力:本节覆盖正文中与「默认切全站 / 写前强依赖 agent」相冲突的表述技术主线松离线、①、形态 B、LWW、超管日志不变。
总原则(采纳宇恒硬约束)未显式开通前,宇恒现网操作与写库逻辑零影响;新能力仅 local_dbsync + 白名单 opt-in。

1. 定案一览

维度 决议
同步模型 松离线写 B最终 UUID+ 接法① dbsync
通道形态 B 本机 sync agent(平台不直连用户 SQLite
冲突 自动 LWW(用户零操作)
落败方可追溯 自动覆盖日志仅平台超级管理员可查(公司 top 不可见)
宇恒默认模式 保持现网local_only 或已在用的 online_primary不自动升 local_dbsync
新模式 显式 YXD_SYNC_MODE=local_dbsync + 表级白名单 才生效
双路径 local_dbsynconline_primary 互斥(同库不同时开)
建表 默认模板仍自增;另增「同步表模板」= UUID TEXT PK入通道校验非 UUID → 拒绝
同步方向(首期) 白名单表 先 B→A;双入口稳定后再开 bidirectional
范围外 不做形态 A、不做终端冲突台、不做 CRDT 字段合并、不对账替代 UUID

2. 比原文「更好」的关键修正

原文偏「目标态替换默认写路径」;协商后改为 旁路增量,避免伤宇恒存量:

原文风险 决议后
全库强制 UUID / 改默认 create 仅同步模板 + 白名单;旧表旧模板不动
松离线成为默认写语义 local_dbsync 分支;旧分支语义冻结
写前强依赖 agent 心跳(智建初评 C2 作废agent 停也不得导致保存失败;仅开通用户显示「待同步」
双向一上来 首期单向 B→A降低网页↔客户端互盖
LWW 无痕 超管覆盖日志(两边 payload + 胜出策略 + TTL

3. 模式与写路径(宇恒)

local_only      → 只写本地(现网)
online_primary  → HTTP 双写 / 离线 pending现网已落地兼容保留
local_dbsync    → 白名单表:始终写 B+ outbox非白名单仍走该模式下的「本地普通写」且不进同步
未配置          → 不得视为 local_dbsync

网关规则:

  1. 非白名单:不强制 id、允许自增;与现网一致。
  2. 白名单 + local_dbsync:无 id 则客户端补 UUID或 400写 B 成功即返回成功agent 仅异步。
  3. local_dbsync → 行为回到原模式(可回滚)。

4. 智建平台职责(收窄可交付)

P0 内容
入通道校验 UUID TEXT PK + 白名单闭包(父子表一起或拒绝)
ingest/应用面 认客户端 UUID幂等 upsert供本机 agent 推送
LWW 超管审计 独立存储与 API公司 top 403TTL建议 90 天)
version outbox 单调序号为主,时间戳为辅
P1 内容
绑定 API online_db_id 登记/查询,与宇恒 BindingStore 对齐
联网限流 reconcile 仅开通同步的库;设置页「同步修复」可选
单向→双向 按表白名单开关,默认仍 B→A
P2 内容
超管按快照回滚单行
弱提示「已自动合并」 仅开通同步客户端,仍不选边

5. 本机 agent形态 B最小集

  • 嵌入或独立进程;未开通同步可不装
  • 读本地 _ajz_sync_outbox(或等价),按 id 保序推 A支持 delete。
  • 凭证:最小权限、按 online_db_id 隔离、可吊销outbox 敏感列脱敏/加密。
  • 心跳仅用于 UI 状态,不阻断 apply_write

6. 分期(建议排期)

阶段 目标 退出标准
M0 规范:同步表模板、入通道校验、模式三分文档 误配自增表无法进通道
M1 宇恒:local_dbsync 旁路 + 白名单松离线写 B仍可无 agent只落本地 未开通用户回归 = 现网;开通用户离线可见
M2 agent 最小推送 B→A + ingest 幂等 联网后同 UUID 上云、不双行
M3 超管 LWW 覆盖日志 + 限流 reconcile 双入口覆盖可查;公司 top 不可见日志
M4 灰度扩大白名单;评估是否对新客默认 local_dbsync 旧客默认仍不变,除非显式迁移

明确M4 之前不谈「全员切默认」。

7. 统一验收(合并 §9 + 双方 E

不影响原有

  • 默认 / 未开 local_dbsync:现网回归通过(含自增不传 id、原 online_primary 行为)。
  • 非白名单表:不强制 UUID加入通道被拒绝。
  • local_dbsync 后行为回到原模式。
  • 未开通用户:无强制 agent、无新冲突 UI、保存不因同步失败。

开通后(白名单)

  • 离线写 B 立刻可见;联网同 UUID 上 A幂等不双行。
  • agent 停:本地仍可保存 +「待同步」;恢复后追上。
  • 双入口同 PKLWW 符合首期策略(偏本机或按 version落败在超管日志。
  • 公司 top 查覆盖日志 → 403超管可检索/导出。
  • online_primary 互斥,无双路径同时写。

8. 协商一句话

技术上走松离线 + 本机 agent + dbsync + LWW超管可追溯产品上必须旁路 opt-in——默认不影响宇恒原有操作白名单灰度达标前不切默认。


宇恒追加-继续协商(第二轮)

说明:在「协商决议版」之上的第二轮协商意见,不改写 §1§12 与决议正文;请智建对「待拍板」表态后可并入决议修订。
立场:决议版 总原则 + §1/§2/§6/§7「不影响原有」 已对齐宇恒硬约束 → 宇恒原则上接受决议版开工。下列为收口与防回潮。

1. 宇恒对决议版的表态

决议要点 宇恒态度
默认不升 local_dbsync;旁路 opt-in 接受(硬条件,不可回退)
默认建表仍自增;同步模板另增 接受
写前不因 agent 停而保存失败 接受(硬条件);请同步作废智建初评 C2「写前强依赖心跳」表述
首期 B→AM4 前不谈全员默认 接受
分期 M0→M4 接受;建议 M1 退出标准增加「未开通用户自动化回归套件」
超管 LWW 日志 / 公司 top 403 接受(宇恒侧无异议)

一句话:可以按决议版排期;宇恒侧合入准则仍是——未开通用户 diff 行为 = 0

2. 请智建确认(防与初评打架)

# 议题 宇恒主张 需要智建回复
R1 agent 与保存 心跳只驱动 UI,永不 apply_write 失败 书面确认作废「写前探测失败则拒绝保存」
R2 双端建表 「同时改」= 只加同步模板,默认模板不动 确认智建控制台默认建表仍自增
R3 关 HTTP 双写 M4 只评估新客显式迁移客;旧 online_primary 客户保留 确认不会「灰度达标后一刀切关双写」
R4 弱提示「已自动合并」 local_dbsync 开通用户;默认关闭,配置打开 避免未开通用户弹任何同步文案

3. 仍待拍板(建议写进决议修订)

# 缺口 建议默认(宇恒提案) 理由
O1 白名单存在哪 智建通道配置为源;宇恒本地缓存副本;以通道为准 防两端名单漂移;未拉到名单前当未开通
O2 谁有权改白名单 公司 top现「数据同步」终端用户只读 与现权限一致;避免用户误加自增表
O3 M1 无 agent 时「开通同步」含义 允许:仅本地松离线 + 待同步积压;产品文案写「需 agent 才上云」 方便分期,但不承诺已上云
O4 Binding API 是否挡 M2 不挡M2 可用现网派生 online_db_idP1 再对齐登记 降低串行依赖
O5 version 授时 优先 outbox 单调 id;客户端 updated_at 仅辅助;不对时不挡保存 落实「不影响保存」
O6 同库表级互斥 决议写「同库互斥」偏严;提案改为:同表不可双路径;同库可「部分表 local_dbsync、其余保持原模式写本地」 更贴白名单灰度,少逼整库切模式
O7 存量 online_primarylocal_dbsync 另附迁移手册:先加白名单→装 agent→双跑观察→关 HTTP禁止静默迁移 保护已上线双写客户

4. 宇恒侧本期承诺(换智建确认 R1R4

  1. M0/M1模式三分 + 白名单判断进 apply_write旧分支零行为 diff(附回归清单)。
  2. 不把 agent 做成安装强依赖。
  3. 同步 UI 与开关仅在开通后出现。
  4. M2 起才对接 ingest协议以智建文档为准客户端不自造第二套写语义。

5. 建议智建本期承诺

  1. 入通道 UUID + 闭包校验M0
  2. ingest 幂等认客户端 UUIDM2 前就绪)。
  3. 超管审计 API 与租户控制台分离M3
  4. 发版说明写明:默认客户无感local_dbsync 为增值开通。

6. 第二轮协商一句话

决议版方向已收束;宇恒同意开工。请智建确认 R1R4并拍板 O1O7尤其 O6 同表互斥 vs 同库互斥)后,即可冻结决议修订版进入 M0。


最终冻结说明2026-07-31

R1R4、O1O7 已全部拍板并写入 松离线-dbsync方案-最终版.md
此后改需求只改最终版并备注变更记录;本过程稿不再作为实施口径。