已关闭
【dolphin 缺陷】>16MB 大结果(单字段/单行)读回失败:出站消息未按 0xFFFFFF 分包 #1629
Rourou2285创建于  19 天前关闭于  9 天前
Rourou2285
Rourou2285
19 天前 创建

背景

MySQL 协议中,当单条服务端→客户端消息(如一行含 >16MB 大字段的结果集)超过 0xFFFFFF(16MB-1)时,服务端应把消息拆成多个 payload 分包发送,并在每个包头上按 3 字节长度 + 递增的 sequence id 标识;消息长度恰为 0xFFFFFF 整数倍时还需补一个空包收尾。客户端再按同样规则重组。

dolphin 的入站方向已支持该重组(上游 fcd035ced fix: support MySQL multi-payload message reassembly,见 Plugin MR !2538),但出站方向未实现对称分块,导致 >16MB 的大结果(单 BLOB/BYTEA 字段或超长单行)读回失败。

现象

实习 #44(mysql crate 兼容性矩阵)实测(P7 用例):

  • 写入方向 OK:17MB BLOB 经 prepared statement / SEND_LONG_DATA 精确落库,LENGTH 正确 = 17825915(入站多包重组已生效);
  • 读回方向 FAILSELECT data 取回该 17MB 字段,客户端只收到少量字节(首 512B 即截断/错乱)。100KB 内完整逐字节回读正常,仅在单消息 >16MB 时触发。

根因

contrib/dolphin/plugin_protocol/bytestream.cpp 的出站函数 dq_putmessage()

uint32 num = len;                 // 包头长度字段只有 3 字节(低 24 位)
for (; i < BYTE_3_LEN; i++) { header[i] = num & 0xff; ... }
header[i] = u_sess->proc_cxt.nextSeqid++;
internal_putbytes(packet, len);   // 正文一次性整包发送

len > 0xFFFFFF 的消息:包头只编码低 24 位、正文整段直接跟上,没有按 0xFFFFFF 分包、seq id 也不逐包递增,字节流直接错位,客户端重组失败 → 表现为结果截断/乱流。

修复思路(供参考,与入站 fcd035ced 对称)

dq_putmessage() 中循环发送:

  1. len > 0xFFFFFF 时拆成若干块,每块 payload 长 0xFFFFFF(最后一块为剩余真实长度),每个包头写各自 payload 长度、seq id 逐包递增;
  2. 若消息总长为 0xFFFFFF 的整数倍,末尾补一个 payload 长度 0 的空包收尾(与客户端预期一致)。

备注

likedislike
opengauss_bot
opengauss_bot成员
19 天前 评论:

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成员
19 天前 将 TestManager 设为负责人
opengauss_botopengauss_bot成员
19 天前 添加了label:sig/Plugin
opengauss_bot
opengauss_bot成员
19 天前 评论:

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
17 天前 关联了pull request:fix: 出站消息按 0xFFFFFF 分包,修复 >16MB 大结果(单字段/单行)读回失败
liuzhen001liuzhen001成员
14 天前 关联了看板:openGauss 7.0.0-LTS
ywzq1161327784ywzq1161327784成员
13 天前 移除了负责人 TestManager
opengauss_bot
opengauss_bot成员
13 天前 评论:

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成员
13 天前 将 TestManager 设为负责人
ywzq1161327784ywzq1161327784成员
13 天前 将 superlchf 设为负责人,移除负责人 TestManager
Rourou2285Rourou2285
12 天前 关联了pull request:【回合 7.0.0】dolphin MySQL 协议修复回合(出站>16MB 分包 / OK·EOF 事务标志 / prepared 参数剥离高位标志)
Rourou2285
Rourou2285
11 天前 评论:

验证结果:通过(PASS)

测例:大结果(>16MB)逐字节回读(examples 测例链接 https://atomgit.com/opengauss/examples/merge_requests/112

载荷由服务端生成后读回(隔离客户端写入路径,直接判定出站分包):

用例 覆盖 结果
BR16 / BR17 1MB,文本 / 二进制协议逐字节回读 PASS
BR18 / BR19 0xFFFFFF−1,文本 / 二进制协议 PASS
BR20 / BR21 ==0xFFFFFF(空包收尾),文本 / 二进制协议 PASS
BR22 0xFFFFFF+1(满块+尾包),二进制协议 PASS
BR23 2×0xFFFFFF(多块),文本协议 PASS
BR24 / BR25 周期模式 + 尾标记逐字节内容校验,文本 / 二进制 PASS
BR26 3 行 ×(0xFFFFFF+1) 多行回读 PASS

BR16–BR26:11/11 PASS。

likedislike
Ssuperlchf成员
11 天前 issue状态由 待办的 改变为 待回归
Ssuperlchf成员
11 天前 issue状态由 待回归 改变为 已完成
Ssuperlchf成员
11 天前 issue状态由 已完成 改变为 待回归
superlchf成员
9 天前 评论:

image.png
测试该用例的26个测试用例,下面只列出其中11个与本issue相关用例通过测试
image.png

likedislike
ywzq1161327784ywzq1161327784成员
9 天前 issue状态由 待回归 改变为 已验收
ywzq1161327784ywzq1161327784成员
9 天前 关闭了 issue