matrixorigin / matrixorigin/matrixone

[Bug]: CN 垂直扩容迁移破坏在途分布式 Pipeline

Open
#27,776 8 comments 0 reactions 1 assignee Claimed by @Ariznawlll View on GitHub
kind/bug severity/s0
Dominant language
Go
Stars
1.9k
Forks
311
Avg merge
1d 3h
Merged PRs (30d)
768

Description

## 问题描述

CN 垂直扩容迁移可能破坏仍在源 CN 上运行的分布式查询 remote pipeline。

在 `4.2-dev` AP Regression 中,执行 `q32_payment_details_business.sql` 时,承载其远端执行分支的 CN 从 `Bound` 迁移至 `Draining`,随后 remote stream 被关闭。Coordinator 返回 `rpc stream closed`,客户端最终收到 MySQL 2013。

原始复现 SQL 包含 `WITH RECURSIVE + bkpf/bseg`,但控制面和数据面证据均表明:**该问题并非递归 CTE 特有问题,也不是长连接超时问题**。只要分布式查询仍有 remote scope 在被迁移的 CN 上运行,都可能受到影响。

## 环境

- 分支:`4.2-dev` 部署线
- 故障 Commit:`d2393868a7aaa6343518d80849fe4696aa3577e9`
- 故障镜像:`matrixone:v4.2.0-d2393868a-2026-08-26`
- 部署环境:cn-dev `freetier-01`,多 CN 集群
- 数据集:`jinpan_001`
- 源 CN:`cn-qtqz2`
- 迁移目标 CN:`cn-p6z9t`
- CN Claim:`freetier-01-shared-medium-qz2g4`
- 时间:2026-08-27 至 2026-08-28

## 复现步骤

1. 使用启用了动态 CPU/内存配额和 CNClaim 迁移的多 CN 部署。
2. 执行一个会在 Worker CN 上长期保留 remote pipeline scope 的分布式查询。原始 SQL 形态如下:

```sql
INSERT INTO jst_receipts_tables.payment_details__stg (...)
WITH RECURSIVE acct_tree AS (...),
acct_payment_type AS (...)
SELECT ...
FROM dwd_dcp.dwd_s4_bkpf b
JOIN dwd_dcp.dwd_s4_bseg s ...;
```

3. 施加足够的并发 CPU/内存压力,使 scale-agent 通过迁移路径提升 Worker CN 的动态配额。
4. 观察 CNClaim 状态、源 CN Ready 状态、remote pipeline stream、Coordinator 错误以及前端连接。

原始执行入口:

- Run:https://github.com/matrixorigin/mo-nightly-regression/actions/runs/33089221059
- Job:https://github.com/matrixorigin/mo-nightly-regression/actions/runs/33089221059/job/98577942963

## 实际行为

客户端返回:

```text
(2013, 'Lost connection to MySQL server during query')
```

Coordinator 记录:

```text
status=fail, error="rpc stream closed"
statement_id=01a043f4-c364-7699-b356-9c31d40fe896
trace_id=3cfa6766-0dae-9e5b-70a5-3f18a6c511f5
```

事件窗口内没有 `OOMKilled`。故障发生在 runner 的 3600 秒 SQL timeout 之前。

### 关联时间线(UTC)

1. `cn-qtqz2` 正在承载 q32 的 remote scope,同时还在执行一条 CPU/内存开销较高的 ACDOCA Window 查询。
2. `16:08:08`,RSS 超过 CN 动态内存配额后,`cos scale-agent` 选择了迁移路径:

```text
update pod quota (migrate)
```

当时 RSS 约为 `49.97–52.70 GB`,动态配额约为 `49.39 GB`,尚未达到 hard memory limit。
3. `unit-agent` 开始将 claim `freetier-01-shared-medium-qz2g4` 从 `cn-qtqz2` 迁移至 `cn-p6z9t`。
4. `16:09:25`,`matrixone-operator` 开始执行 `migrate claimed pod`。
5. 源 CN 从 `Bound` 转为 `Draining`,约在 `16:09:30` 变为 NotReady。
6. `16:10:24`,Coordinator `cn-vldrc` 到 `cn-qtqz2:6002` 的 remote stream 关闭,Receiver context 随后被取消。
7. `16:11:00`,q32 以 `rpc stream closed` 结束;前端连接关闭,客户端收到 MySQL 2013。

已确认的故障链路为:

```text
资源压力
-> CN 垂直扩容迁移
-> 源 CN Draining/NotReady
-> 在途 remote stream 关闭
-> rpc stream closed
-> 前端连接关闭 / MySQL 2013
```

资源压力是迁移的触发条件。真正违反的契约是:迁移/排空流程在源 CN 仍有 active distributed pipeline 时就将其退出服务。

## 预期行为

- CN 扩容不能终止仍在源 CN 上运行 remote scope 的分布式查询。
- 源 CN 必须保持可访问,直到 active remote pipeline 和事务完成排空并明确确认。
- 如果强制排空必须中止查询,Coordinator 应收到带类型的 MatrixOne 终止错误。
- Remote Worker 故障不应额外关闭生命周期仍健康的前端 MySQL 连接。
- 客户端不能只收到没有诊断信息的 MySQL 2013。

## 工作负载证据

`16:05–16:10` 期间 `cn-qtqz2` 的 Pyroscope 显示,主要 CPU 路径为:

```text
window.processFunc
-> sumDecimal128FastExec.batchFill
```

该路径对应一条并发执行的 ACDOCA 查询,其中包含两个几乎相同、通过 `UNION ALL` 连接的 Window 分支。它对扩容决策产生了实质影响。q32 是分布式查询受害者;现有证据不支持将递归 CTE 执行视为触发原因。

## 需要修复的契约

1. **CN 迁移/排空契约**
- Active remote pipeline 或事务未结束时,不得解绑、移除源 CN,或使其变得不可访问。
- 创建扩容后的目标 CN 时,应允许已有分布式任务继续在源 CN 上完成。
- 源 CN 退出前必须获得明确的 drain acknowledgement。

2. **Remote pipeline 终止契约**
- 向 Coordinator 传播明确的 CN-draining/worker-unavailable 终止信号。
- Sender、Receiver、取消和清理路径都必须正常结束,不能出现 hang 或泄漏。

3. **前端错误契约**
- 强制终止 remote pipeline 时,应返回可诊断的 MatrixOne 错误。
- 如果前端连接本身仍然健康,应保留该连接。

## 回归验证

修复后,在原始 q32 remote scope 仍处于 active 状态时触发 CN 垂直扩容迁移,至少重复执行 3 次,并验证:

1. 查询正常完成;如果必须强制排空,则返回带类型的 MatrixOne 错误。
2. Active remote pipeline 结束前,源 CN 不会退出服务。
3. 不出现 `rpc stream closed`、无法解释的 `context canceled` 或 remote receiver hang。
4. 查询级错误之后,前端连接仍可继续使用。
5. 不发生 CN 崩溃、资源泄漏或无限期阻塞的迁移。
6. 后续 SQL 和新连接均正常。

仅升级并验证较新的 `4.2-dev` 镜像并不足够,测试必须覆盖 CNClaim 迁移/排空路径。调查时当前部署版本为 `v4.2.0-602c4dd7d-2026-08-28`,尚不是 `635de0535a`。后者包含 remote pipeline/backpressure 修复,但目前没有证据表明它改变了上述迁移/排空契约。

## 独立发现

以下问题发生在同一轮 Regression 中,但不是本 Issue 跟踪的直接原因:

- `cn-4l2ht` 上的 `S3FS.Write -> panic("found EOF in Write")` 是独立的 CN 崩溃问题。
- q32 的 staging INSERT 失败后,测试仍继续执行 `RENAME`/`DROP`。这可能用空表或不完整的 staging 表替换目标表;INSERT 失败时,脚本/runner 必须在交换表之前停止。

## 相关链接

- 调查结论:https://github.com/matrixorigin/matrixone/issues/27776#issuecomment-5448472188
- 相关 Issue:https://github.com/matrixorigin/matrixone/issues/25803
- 之前的 MORPC 修复:https://github.com/matrixorigin/matrixone/pull/25811
- 连接保活修复:https://github.com/matrixorigin/matrixone/pull/27156
- 调查时最新的 `4.2-dev` backport:https://github.com/matrixorigin/matrixone/commit/635de0535a21807c02ee49f37331406921c7889b

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.