已关闭
[Bug]: dolphin OK/EOF 包缺少 SERVER_STATUS_IN_TRANS 导致 SeaORM 事务 BeginFailed #1630
Rourou2285创建于  9月6日关闭于  9月14日
Rourou2285
Rourou2285
9月6日 创建

问题描述

使用 SeaORM(底层为 SQLx 0.8 MySQL 驱动)连接 openGauss B 兼容库(dolphin,DBCOMPATIBILITY 'B')执行 db.transaction() 时,返回 BeginFailed,事务无法开始。

复现方式

use sea_orm::{ConnectionTrait, DatabaseConnection, DbBackend, Statement, TransactionTrait};

db.transaction(|txn| {
    Box::pin(async move {
        // 任意 DML
        Ok::<_, sea_orm::DbErr>(())
    })
})
.await.expect("transaction failed"); // BEGINFAILED

STAR TRANSACTION 之后 SQLx 事务管理器读取响应包的 status_flags 确认事务已开始,缺失 SERVER_STATUS_IN_TRANS 位则判定失败。

根因

dolphin 在构造 MySQL OK/EOF 包的 status_flags 字段时只设置了 SERVER_STATUS_AUTOCOMMIT(及多语句时的 SERVER_MORE_RESULTS_EXISTS),没有根据当前是否处于事务块设置 SERVER_STATUS_IN_TRANS。因此客户端在 START TRANSACTION 后无法确认事务已真正开始。

修复

在 contrib/dolphin/plugin_protocol/dqformat.cpp:

  • send_network_ok_packet():当 IsTransactionBlock() 时给 server_status 或上 SERVER_STATUS_IN_TRANS;
  • sendServerStatus()(EOF 包路径复用):同样处理;
  • 新增 #include "access/xact.h"。

验证

  • 修复前:SeaORM db.transaction() 返回 BeginFailed。
  • 修复后:事务内 insert/update 成功,count=2,[PASS] transaction。

结论

为符合 MySQL 协议语义,OK/EOF 包的状态位应反映事务状态。这是协议状态位补全,不影响其它路径。

关联 MR:基于 seaorm-fix-intrans 分支提交。

likedislike
opengauss_bot
opengauss_bot成员
9月6日 评论:

This issue requires an assignee. Since you haven't specified one, we've assigned TestManager as the default assignee for this issue.

likedislike
opengauss_botopengauss_bot成员
9月6日 将 TestManager 设为负责人
opengauss_botopengauss_bot成员
9月6日 添加了label:sig/Plugin
opengauss_bot
opengauss_bot成员
9月6日 评论:

Welcome To openGauss Community

Hey @Rourou2285 , thanks for your contribution to the community.

Bot Usage Manual

I'm the Bot here serving you. You can find the instructions on how to interact with me at Here . That means you can comment below every pull request or issue to trigger Bot Commands. You can self-configure the PR merge rules for this repository. For more details, please refer to Here.

Contact Guide

If you have any questions, please contact the SIG: Plugin ,
and any of the maintainers: @CarrotGo, @chendong76, @chenxiaobin19, @congzhou2603, @dodders, @hwworkholic, @jemappellehc, @libiao2024, @muyulinzhong, @quemingjian, @shenzheng4, @shirley_zhengx, @superlchf, @totaj, @wlff234, @wofanzheng, @ywzq1161327784 ,
and any of the committers: @dreamalloc, @huyinghao, @libiao2024, @wangfeihuo, @wmy_ld, @wuyuechuan, @xiong_xjun, @zhangxubo, @zhaojunv3z810 .

likedislike
Rourou2285Rourou2285
9月6日 关联了pull request:[dolphin] SeaORM: 修复 OK/EOF 包缺 SERVER_STATUS_IN_TRANS 导致事务 BeginFailed
liuzhen001liuzhen001成员
9月9日 关联了看板:openGauss 7.0.0-LTS
ywzq1161327784ywzq1161327784成员
9月10日 移除了负责人 TestManager
opengauss_bot
opengauss_bot成员
9月10日 评论:

This issue requires an assignee. Since you haven't specified one, we've assigned TestManager as the default assignee for this issue.

likedislike
opengauss_botopengauss_bot成员
9月10日 将 TestManager 设为负责人
ywzq1161327784ywzq1161327784成员
9月10日 将 superlchf 设为负责人,移除负责人 TestManager
Rourou2285Rourou2285
9月10日 关联了pull request:[实习#45] SeaORM 兼容性测试工程(含 #1630/#1631 测试用例)
Rourou2285Rourou2285
9月11日 关联了pull request:【回合 7.0.0】dolphin MySQL 协议修复回合(出站>16MB 分包 / OK·EOF 事务标志 / prepared 参数剥离高位标志)
Rourou2285
Rourou2285
9月12日 评论:

验证结果:通过(PASS)

测例:SeaORM transactions 模块(examples 测例链接 https://atomgit.com/opengauss/examples/merge_requests/115)

用例 覆盖 结果
TX1 db.transaction() 提交 PASS
TX2 事务回滚 PASS
TX3 连续 3 个事务 PASS
TX4 原始 SQLx BEGIN/COMMIT PASS
TX5 原始 SQLx 回滚 PASS
TX6 事务内结果集(EOF 路径)后提交 PASS
TX7 SAVEPOINT + ROLLBACK TO SAVEPOINT 后提交 PASS
TX8 事务内语句失败后,新事务可正常开启 PASS
TX9 SET autocommit=0 + COMMIT PASS
TX10 事务隔离:未提交不可见 / 提交后可见 PASS
likedislike
Ssuperlchf成员
9月12日 issue状态由 待办的 改变为 已完成
Ssuperlchf成员
9月12日 issue状态由 已完成 改变为 待回归
superlchf成员
9月14日 评论:

测试通过:
image.png

likedislike
ywzq1161327784ywzq1161327784成员
9月14日 issue状态由 待回归 改变为 已验收
ywzq1161327784ywzq1161327784成员
9月14日 关闭了 issue
wangzecheng00970482
wangzecheng00970482成员
8 天前 评论:

20261010转测包自测无误
image.png

likedislike
wuchenlong
wuchenlong成员
6 天前 评论:

回归版本:8.0.0-RC1.B001(select version() = (openGauss 7.0.0 build 6a41b1ba) compiled at 2026-10-10 13:02:14;version.cfg = openGauss-Server-7.0.0 / 93.164 / 6a41b1ba / release;8.0.0-RC1 内部版本号仍为 7.0.0,属正常)
回归环境:224 lts 集群(ARM,cluster_state=Normal),B 兼容库 reg_b1630(DBCOMPATIBILITY 'B',dolphin 5.3);主库 enable_dolphin_proto=off 为 postmaster 级 GUC(需重启),按纪律未重启集群,协议层改用同一 gaussdb 二进制(sha256 b2216016…badf7,与主集群运行进程一致)的临时独立实例(15630 + dolphin 3308)实测,测完已停实例、释放端口、删除临时数据目录
结论:通过(BEGIN/START TRANSACTION 后 OK 包 status_flags=0x0203 含 SERVER_STATUS_IN_TRANS,事务内结果集 EOF 包同样置位,COMMIT/ROLLBACK 正确清零,11/11 PASS,无 BeginFailed)

说明与验证明细

select version() → (openGauss 7.0.0 build 6a41b1ba) compiled at 2026-10-10 ... commit 1002 last mr 9772 release(8.0.0-RC1 内部版本号仍为 7.0.0,正常);version.cfg → openGauss-Server-7.0.0 / 93.164 / 6a41b1ba / release。

B 兼容库:reg_b1630(DBCOMPATIBILITY 'B',dolphin 5.3)

环境准备

-- gsql -d postgres -p 15600 -r
CREATE DATABASE reg_b1630 DBCOMPATIBILITY 'B';
\c reg_b1630
create extension dolphin;
\c reg_b1630
drop table if exists tx_t;
create table tx_t(id int primary key, v int);
insert into tx_t values (1, 100);

验证方式

  1. 字节级 MySQL 协议(自写 raw 客户端):直接解析每个 OK 包 / EOF 包的 status_flags 字段,按 SQLx 0.8 MySQL 事务管理器的语义判定 —— BEGIN 的 OK 包必须含 SERVER_STATUS_IN_TRANS(0x0001),否则即 BeginFailed;事务内结果集的 EOF 包同样检查该位。
  2. 真实客户端对照:pymysql 2.2.8(conn.begin() 后读 server_status)、go-sql-driver/mysql v1.8.1(db.Begin()/Insert/Commit 往返)、mysql CLI 8.0.45 连通性。
  3. 协议层实测说明:主库 15600 的 enable_dolphin_proto=off 且为 postmaster 级 GUC(开启需重启集群),为不重启集群,使用同一份 gaussdb 二进制(sha256 b2216016…badf7,与主集群运行进程 /proc/20458/exe 一致)起了临时独立实例(15630 + dolphin 3308);临时实例已停、端口已释放、临时数据目录已删除,主集群未做任何改动。

关键结果(11/11 PASS)

[PASS] TX1 db.transaction() commit      BEGIN=0x0203[IN_TRANS=1 AUTOCOMMIT=1]; DML OK=0x0203[IN_TRANS=1]; COMMIT=0x0202[IN_TRANS=0]; count=2
[PASS] TX2 transaction rollback         ROLLBACK=0x0202[IN_TRANS=0]; count 不变
[PASS] TX3 three consecutive transactions   BEGIN=0x0203 ×3 / COMMIT=0x0202 ×3
[PASS] TX4 raw BEGIN/COMMIT             BEGIN=0x0203; COMMIT=0x0202
[PASS] TX5 raw BEGIN/ROLLBACK           BEGIN=0x0203; ROLLBACK=0x0202; v(id=1)='100'
[PASS] TX6 in-transaction result set (EOF path)  EOF(after cols)=0x0203; EOF(final)=0x0203; COMMIT=0x0202
[PASS] TX7 SAVEPOINT + ROLLBACK TO SAVEPOINT     BEGIN=0x0203; ROLLBACK TO SAVEPOINT=0x0203; COMMIT=0x0202
[PASS] TX8 statement failure then new transaction   err=132; 新 BEGIN=0x0203
[PASS] TX9 SET autocommit=0 + COMMIT     INSERT 0x0201[IN_TRANS=1]; COMMIT 0x0200
[PASS] TX10 transaction isolation        未提交不可见(during=2) / 提交后可见(after=3)
[PASS] TX11 cross-client (pymysql)      conn.begin() server_status=0x0203[IN_TRANS=1 AUTOCOMMIT=1]
VERDICT: db.transaction() equivalent -> PASS (no BeginFailed)

真实客户端 go-sql-driver:[PASS] 1630 go-sql-driver: Begin/Insert/Commit roundtrip OK

结论

START TRANSACTION / BEGIN 后的 OK 包已置 SERVER_STATUS_IN_TRANS(0x0203),事务内结果集 EOF 包同样置位;COMMIT/ROLLBACK 后该位正确清零(0x0202/0x0200)。按 SQLx 0.8 的判定逻辑不再出现 BeginFailed,db.transaction() 等价路径的提交、回滚、连续事务、SAVEPOINT、autocommit=0、事务内结果集 EOF、隔离性等 11 个用例全部通过。issue 描述的现象在 8.0.0-RC1.B001 上未复现,回归通过。

未覆盖:未运行真实 SeaORM/SQLx(169 无已安装 Rust 工具链),改用字节级协议按 SQLx 判定语义等价验证,并用 pymysql / go-sql-driver 两个真实客户端交叉确认;多语句 SERVER_MORE_RESULTS_EXISTS、出站 >16MB 分包等其它协议分支未覆盖。证据:/data1/wcl0623/issue-regression/8.0.0-rc1/results/dolphin/plugin-1630/(verdict.md、evidence/)。

likedislike