已开启
[Bug]: [数据分支] object-scope 冲突无法 resolve,continue 被拒(unresolved non-auto object change public.t_uk (TABLE)) #124
wuchenlong创建于  7 天前
wuchenlong
wuchenlong成员
7 天前 创建

测试类型

接口功能

测试版本

8.0.0-RC1(build latest1027,编译 2026-10-26;neon 扩展 1.1;og_storage 090d116d… / og_compute deea2275…)

问题描述

新 build(openGauss 8.0.0-RC1 / neon 1.1 / build latest1027)下,blocked merge 中 object-scope 冲突无法通过 branch resolve 清除:

  1. manual merge 进入 blocked(本次 215 条冲突),branch resolve --conflict-id <id> --resolution theirs 对全部 conflict_id 逐条执行均返回成功(Resolved conflict ... as theirs);
  2. 但 branch continue 仍被拒:blocked merge <merge_id> contains unresolved non-auto object change public.t_uk (TABLE);
  3. 版本基线(A/B 实测 2026-10-28):旧 build(openGauss 7.0.0 / CP 79c04b9 / 镜像 2026-10-14)在同一 7 条最小复现下 continue 同样 rc=1、错误原文一致;两版 neon 扩展均为 1.1;merge_oggit.rs 79c04b9→34424d9d2 无 diff。故本问题为既有缺陷,非新 build 回归;旧用例通过是场景差异(未同时具备「同对象 ≥2 处非自动变更 + 目标侧同对象变更」)。
  • 影响:对象级冲突进入 blocked 后,用户无法用 CLI 完成处置(resolve 显示成功但 continue 仍拒),blocked merge 永久无法收敛,只能 abort 重来;写屏障期间 target 不可写,影响业务。
  • 建议修复方向:让 branch resolve 支持 object-scope 冲突(ours/theirs/skip/custom SQL)并在内部状态上真正清除「unresolved non-auto object change」;或在 branch conflicts / 错误信息中明确给出对象级冲突的解决入口/所需 SQL。

临时仓库提单,待与产品/开发确认后转正式仓。

版本基线(A/B 对照)

实验时间 2026-10-28;同一 7 条最小复现分别跑旧/新 build(脚本 env/repro/issue124_script_oldbuild.sh / issue124_script.sh,详版 env/repro/OLDVSNEW_ANALYSIS.md)。

项 旧 build("老版本") 新 build(latest1027)
镜像 og_storage:arm = sha256:309860b487d3…(built 2026-10-14 16:28);og_compute:arm = sha256:3cc5161346b6…(built 2026-10-14 16:53) og_storage:latest1027 = sha256:090d116d9066…(built 2026-10-27 09:31);og_compute:latest1027 = sha256:deea22754a08…(built 2026-10-26 20:06)
openGauss 7.0.0(build 2026-10-14 08:34:05,aarch64) 8.0.0-RC1(build 2026-10-26 10:10:19,aarch64)
neon 扩展 1.1(实测,非 1.0) 1.1(实测)
control_plane commit 79c04b9(2026-10-14) 34424d9d2(2026-10-27)
merge_oggit.rs diff — 79c04b9→34424d9d2 无 diff
merge(child→parent manual) status=blocked,唯一冲突 ddl/object_conflict t_uk(conflict_id 7342) status=blocked,唯一冲突 ddl/object_conflict t_uk(conflict_id 2902)
resolve 成功(Resolved conflict … as theirs) 成功
continue rc=1:blocked merge … contains unresolved non-auto object change public.t_uk (TABLE) rc=1,同一错误原文
oggit.object_change 中 t_uk 行 279 行(历史累积);本次两处 DDL 均已记录,safety_class 为 semantic/destructive 295 行(历史累积);本次两处 DDL 均已记录,safety_class 为 semantic/destructive

结论:旧 build 同样复现 → #124 是既有缺陷,不是新 build 回归;merge_oggit.rs 无 diff、两版 ext 均为 1.1、object_change 分类一致。旧用例通过只是场景差异。修复需在 79c04b9 与 34424d9d2(及后续)两版同时验证/修复。

最小复现(7 条命令,2/2 稳定复现,build latest1027)

前置:Docker neon_poc,build latest1027(openGauss 8.0.0-RC1 / neon 1.1)。脚本从 main 派生临时 pair 父/子 endpoint(示例 r124p<后缀>/r124c<后缀>,端口 55644/55645,--enable-oggit --oggit-database postgres),不触碰 main/dev1/main2;两端 public.t_uk 基线为 k1 text, v text(从 main 继承)。账号 branch_merge / Branch_merge@123,库 postgres。

# 0)(脚本自动完成,不计入 7 条)建临时 pair:P=r124p<后缀>(55644,来自 main)、C=r124c<后缀>(55645,来自 P)
#    以下 <MID> 为 merge 输出的 merge_id

# 1) 子侧:同一对象 t_uk 的非自动对象变更①(semantic)
gsql -p 55645 -c "ALTER TABLE t_uk ALTER COLUMN k1 TYPE varchar(48);"

# 2) 子侧:同一对象 t_uk 的非自动对象变更②(destructive)
gsql -p 55645 -c "ALTER TABLE t_uk DROP COLUMN v;"

# 3) 父侧:同一对象 t_uk 的另一处变更(safe_additive,制造 object_conflict)
gsql -p 55644 -c "ALTER TABLE t_uk ADD COLUMN pcol int;"

# 4) 子→父 merge(manual)→ blocked
neon_local branch merge --source-endpoint r124c<后缀> --target-endpoint r124p<后缀> --database postgres --incremental-oggit --strategy manual
# 输出: merge_id=<MID> status=blocked conflicts=1 applied=0

# 5) 查看冲突:仅 1 条 ddl/object_conflict(子侧第二处非自动变更没有 conflict 行)
gsql -p 55644 -c "SELECT conflict_id, conflict_scope, conflict_type, object_name FROM oggit.merge_conflict WHERE merge_id='<MID>';"

# 6) resolve 全部冲突 → 命令成功
neon_local branch resolve --target-endpoint r124p<后缀> --database postgres --merge-id <MID> --conflict-id 2902 --resolution theirs
# 输出: Resolved conflict 2902 ... as theirs

# 7) continue → 仍被拒(缺陷现象)
neon_local branch continue --target-endpoint r124p<后缀> --database postgres --merge-id <MID>
echo "rc=$?"

实际输出(原样;run1 merge_id=51bea013-a676-4bcb-8e5a-0382e4b380ca,run2=1fd2cb99-e12f-4f54-8a48-0ae7689dd8f8 同构,错误原文一致 → 2/2 稳定)

# 4) merge
oggit.merge	merge_id=51bea013-a676-4bcb-8e5a-0382e4b380ca	status=blocked	conflicts=1	applied=0

# 5) conflicts(仅 1 条)
 conflict_id | conflict_scope |  conflict_type  | object_name
-------------+----------------+-----------------+-------------
        2902 | ddl            | object_conflict | t_uk

# 6) resolve(成功)
Resolved conflict 2902 on target branch 'r124pt1' (...) as theirs

# 7) continue(rc=1,缺陷现象)
POST /v1/branch/merge/51bea013-a676-4bcb-8e5a-0382e4b380ca/continue failed: HTTP 500:
{"causes":["failed to continue oggit merge","blocked merge 51bea013-a676-4bcb-8e5a-0382e4b380ca contains unresolved non-auto object change public.t_uk (TABLE)"],"error":"failed to continue oggit merge"}
rc=1

期望:resolve 成功后 continue 应 applied;continue 不应把没有对应 conflict 行的对象变更当作未处理项拒绝(CLI 也没有其他入口消除该状态)。

根因(一句):merge 规划阶段 control_plane/src/bin/merge_oggit.rs 按 object_key 去重、同一对象只落 1 条 object conflict;continue 阶段逐条遍历 source 侧 object_change 时第 2 条变更找不到匹配 conflict,且 child→parent 仅 safe_additive|requires_validation 可自动(semantic/destructive 返回 false),于是直接 bail!("blocked merge ... contains unresolved non-auto object change ...")。

与完整用例的关系:原 ### 完整场景(L-MRG-08,215 条冲突)包含行冲突与历史 object_change 累积;本最小复现去掉行冲突与历史依赖,只需「同一对象 ≥2 处非自动变更(semantic/destructive) + 目标侧该对象有变更」即可稳定触发。

复跑脚本:env/repro/issue124_script.sh <任意后缀>(期望末行 REPRO OK (continue rc=1));详版记录见 env/repro/issue124_minimal.md。

操作系统和硬件信息

openEuler 24.03 LTS-SP2 aarch64(Docker 容器化,arm 镜像)

测试环境

轻量版容器化(Docker neon_poc 数据分支实验环境:main 55432 / dev1 55435 / main2 55436;账号 branch_merge;两端 oggit active)

被测功能

数据分支 merge 生命周期:blocked merge 的 conflicts / resolve / continue(object-scope 冲突处置)

预置条件

  1. 部署:Docker neon_poc(数据分支实验环境),build latest1027;openGauss 8.0.0-RC1(编译 2026-10-26),neon 扩展 1.1。
  2. endpoint:main = 55432,dev1 = 55435(另 main2 = 55436);两端以 --enable-oggit --oggit-database postgres 启动,oggit worker 状态 active。
  3. 账号:branch_merge(Branch_merge@123);业务表基线 items(id int primary key, name text, price int, v text) 两端同构。
  4. 客户端:source /opt/neon-work/scripts/env.sh 后使用 neon_local(docker_local)与 gsql。

完整场景(原记录,215 条冲突)

source /opt/neon-work/scripts/env.sh
cd /opt/neon-work/branching

# 1) 构造同列冲突并进入 blocked
gsql -d postgres -U branch_merge -W 'Branch_merge@123' -h 127.0.0.1 -p 55435 -c "UPDATE items SET name='c100' WHERE id=100;"
gsql -d postgres -U branch_merge -W 'Branch_merge@123' -h 127.0.0.1 -p 55432 -c "UPDATE items SET name='p100' WHERE id=100;"
neon_local branch merge --source-endpoint dev1 --target-endpoint main --database postgres --incremental-oggit --strategy manual
# 输出: oggit.merge merge_id=<MERGE_ID> ... status=blocked conflicts=215 applied=0
MERGE_ID=<上一步输出的 merge_id>

# 2) 逐条 resolve 全部冲突(含 object scope)
for cid in $(gsql -d postgres -U branch_merge -W 'Branch_merge@123' -h 127.0.0.1 -p 55432 -tAc \
  "SELECT conflict_id FROM oggit.merge_conflict WHERE merge_id='$MERGE_ID' ORDER BY conflict_id"); do
  neon_local branch resolve --target-endpoint main --database postgres --merge-id $MERGE_ID --conflict-id $cid --resolution theirs
done

# 3) continue
neon_local branch continue --target-endpoint main --merge-id $MERGE_ID --database postgres; echo "rc=$?"

预期输出

# 全部冲突决议后 continue 成功(applied),按原窗口 apply:
oggit.merge	merge_id=...	status=applied	...
rc=0

实际输出

# 1) blocked(215 条冲突)
oggit.merge	merge_id=bd387922-fc10-4102-a039-293eddaca0dd	status=blocked	conflicts=215	applied=0

# 2) resolve 全部 conflict_id(2203..2417 等)均成功
Resolved conflict 2203 on target branch 'main' (...) as theirs
Resolved conflict 2204 on target branch 'main' (...) as theirs
...(逐条 rc=0)...

# 3) continue 仍被拒
$ neon_local branch continue --target-endpoint main --merge-id $MERGE_ID --database postgres
POST /v1/branch/merge/bd387922-fc10-4102-a039-293eddaca0dd/continue failed: HTTP 500: {"causes":["failed to continue oggit merge","blocked merge bd387922-fc10-4102-a039-293eddaca0dd contains unresolved non-auto object change public.t_uk (TABLE)"],"error":"failed to continue oggit merge"}
rc=1
# 后续查询 status 断言失败(仍非 applied):
# CHECK: 失败 ['断言缺失: applied (期望 status=applied)']

日志信息

  • 自动化用例日志:env/runs/all/L-MRG-08.log(pre3 blocked conflicts=215;STEP 2 逐条 resolve 全成功;STEP 3 continue rc=1 + unresolved non-auto object change public.t_uk (TABLE);STEP 5 断言缺失 applied)
  • 新 build 分诊:env/TRIAGE_NEWBUILD.md C 区 L-MRG-08(oldbuild 用例通过=场景差异;A/B 最小复现同样 rc=1 / latest1027=失败,「新 build 对 object conflict 要求显式解决且 CLI 无对应入口」)
  • 版本基线 A/B:env/repro/OLDVSNEW_ANALYSIS.md(旧 build 同样 continue rc=1、错误原文一致;merge_oggit.rs 79c04b9→34424d9d2 无 diff;两版 ext 均为 1.1;object_change 279/295、safety_class 一致)
  • 备注:日志 STEP 1 单条 resolve 因未带 --database 返回 rc=2 属测试侧构造问题,不影响 STEP 2/3 结论。

临时仓库提单,待与产品/开发确认后转正式仓。

提单组织

测试团队

likedislike
wuchenlongwuchenlong成员
7 天前 添加了label:bug
wuchenlongwuchenlong成员
7 天前 修改了issue 的描述
wuchenlongwuchenlong成员
7 天前 修改了issue 的描述