matrixorigin / matrixorigin/matrixone
[Bug]: shardservice HasAllLocalReplicas 将远端副本误判为本地副本
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
### 是否存在相同问题
- [x] 已检索现有 issue。
- 检索到 #19176,但该 issue 的结论是 range/list 分区裁剪缺失;本问题是当前 `shardservice.HasAllLocalReplicas` 丢弃本地性判断结果,根因和白盒复现均不同。
### 分支与提交
- 分支:最新 `main`
- Commit:`826a3e3d294ba62c7c4da217d1445f3c568ce4d9`
- Commit 标题:`fix(colexec): short-circuit flow-control expressions (#25742)`
- 验证日期:2026-07-20
### 问题描述
`pkg/shardservice/service.go` 的 `HasAllLocalReplicas` 用于判断一张表的每个 shard 是否都至少有一个本地 CN 副本。
当前循环调用了 `s.isLocalReplica(replica)`,但没有使用返回值;随后无条件执行 `local++` 并 `break`:
```go
for _, replica := range shard.Replicas {
s.isLocalReplica(replica)
local++
break
}
```
因此,只要每个 shard 的 replica 列表非空,即使所有 replica 都属于其他 CN,也会被计入本地副本数,最终错误返回 `true`。
### 白盒测试用例
构造:
- 当前服务:`ServiceID = cn-local`
- 表 ID:`42`
- shard 1:仅有 `cn-remote-1` 副本
- shard 2:仅有 `cn-remote-2` 副本
- 两个 shard 均没有 `cn-local` 副本
核心断言:
```go
allLocal, err := s.HasAllLocalReplicas(tableID)
require.NoError(t, err)
require.False(t, allLocal,
"remote-only replicas must not be counted as local replicas")
```
### 执行命令
原始代码定向复现:
```bash
go test ./pkg/shardservice \
-run '^TestAuditHasAllLocalReplicasRejectsRemoteOnlyShards$' \
-count=3 -v
```
原始代码 race 复现:
```bash
go test -race ./pkg/shardservice \
-run '^TestAuditHasAllLocalReplicasRejectsRemoteOnlyShards$' \
-count=1 -v
```
临时应用最小修正后的稳定性验证:
```bash
go test ./pkg/shardservice \
-run '^TestAuditHasAllLocalReplicasRejectsRemoteOnlyShards$' \
-count=100
go test -race ./pkg/shardservice \
-run '^TestAuditHasAllLocalReplicasRejectsRemoteOnlyShards$' \
-count=50
```
### 实际结果
原始代码普通测试 3 次全部失败:
```text
Error: Should be false
Messages: remote-only replicas must not be counted as local replicas
--- FAIL: TestAuditHasAllLocalReplicasRejectsRemoteOnlyShards
FAIL
```
原始代码 race 测试同样失败,返回值稳定错误;未发现数据竞争。
临时将循环改为仅在 `isLocalReplica(replica) == true` 时执行 `local++` 后:
- 普通测试:`100/100 PASS`
- race 测试:`50/50 PASS`
验证完成后已撤销生产代码修正,仅保留本地未提交的审计测试;未提交、未推送任何代码。
### 期望结果
只有当表的每一个 shard 都至少存在一个 `replica.CN == s.cfg.ServiceID` 的副本时,`HasAllLocalReplicas` 才应返回 `true`。远端副本不能计入本地副本数。
### 影响评估
该方法公开在 `ShardService` 接口中,返回错误结果可能使调用方误走“全部 shard 均在本地”的执行路径。当前 main 仓库内未检索到生产调用点,因此属于已确认的潜伏逻辑错误,但接口语义与实现明确不一致。
Contributor guide
Assessment
This issue has not been assessed yet.