Skip to content

store/mysql 与 cache 层存在 5 处缺陷:SQL 列名错误、namespace metadata 未持久化、创建泳道组 panic #1430

Description

@chirschou

Describe the bug

在为 store 层适配 PostgreSQL 的过程中,逐条执行 store/mysql 中的 SQL 时发现 5 处缺陷。它们与具体数据库无关,在 MySQL 部署下同样存在,其中 3 处会导致对应功能完全不可用。


1. namespace 的 metadata 未持久化

位置store/mysql/namespace.go

DDL 中 namespace 表有 metadata 列,model.NamespaceMetadata 字段,namespace/namespace.go:357 也会把它放进 API 响应,但 store 层的 INSERT / UPDATE / SELECT 三处都没有涉及该列(全文搜索 metadata 命中 0 次)。结果是写入被丢弃、读取恒为空。

store/boltdb/namespace.go 对该字段是完整支持的(存取共 6 处),因此只有使用 MySQL 的部署受影响。

影响:polaris-console 依赖 namespace 的 metadata 判断全局注册中心(checkGlobalRegistry),该函数因此恒返回 false;同时前端对 undefined 调用 Object.entries 会导致命名空间等页面白屏。


2. client_stat 的列名错误

位置store/mysql/client.go:235store/mysql/client.go:458

// 235: FROM 中只有 client_stat,并无 client 表
str := "select `target`, `port`, `protocol`, `path` from client_stat where client.id = ?"

// 458: cliend_id 是 client_id 的拼写错误
deleteStr := "delete from client_stat where cliend_id = ?"

client_stat 表只有 client_id 列。两条 SQL 执行必然报 Unknown column

影响GetClientStatupdateClientStat 一直不可用。


3. BatchCleanDeletedClients 参数数量不匹配

位置store/mysql/admin.go:536

mainStr := "delete from client where flag = 1 limit ?"          // 1 个占位符
result, err := tx.Exec(mainStr, int32(timeout.Seconds()), batchSize)  // 传入 2 个参数

除参数数量不符外,timeout 实际未参与过滤,与同文件中 BatchCleanDeletedInstances(按 mtime 过滤)的语义也不一致。

影响:客户端软删除数据的清理任务执行失败。


4. auth_role_principal 的列名与占位符错误

位置store/mysql/role.go:68store/mysql/role.go:73

// 68: 该表的关联列是 role_id,不存在 id 列
tx.Exec("DELETE FROM auth_role_principal WHERE id = ?", role.ID)

// 73: 列列表中出现函数;且四个列只给了三个占位符,而下方传入四个参数
insertTpl := "INSERT INTO auth_role_principal(role_id, principal_id, principal_role, IFNULL(extend_info, '')) VALUES (?, ?, ?)"

(同文件 270 行 SELECT 中的 IFNULL(extend_info, '') 是正常用法,不在此列。)

影响:角色携带 Users / UserGroups 时,savePrincipals 必然失败,即角色的成员关联功能不可用。


5. LaneCache.GetRule 空指针 panic

位置cache/service/lane.go:430

func (lc *LaneCache) GetRule(id string) *model.LaneGroup {
	rule, _ := lc.rules.Load(id)
	return rule.LaneGroup
}

忽略了 SyncMap.Load 的 ok 返回值,直接对可能为 nil 的结果解引用。调用方 service/interceptor/auth/lane.go:128 写有 if saveRule != nil 判断,说明其预期该函数可以返回 nil。

创建泳道组时 req[i].GetId() 为空字符串,必然命中该路径。

影响:创建泳道组的请求触发 panic,连接被服务端断开(HTTP 无响应)。该功能完全不可用。

To Reproduce

问题 5 可直接复现:

curl -XPOST "http://127.0.0.1:8090/naming/v1/lane/groups" \
  -H "X-Polaris-Token: $TOKEN" -H "Content-Type: application/json" \
  -d '[{"name":"lane1","namespace":"default","description":"d"}]'

服务端日志:

http: panic serving 127.0.0.1:60605: runtime error: invalid memory address or nil pointer dereference
github.com/polarismesh/polaris/cache/service.(*LaneCache).GetRule
	/cache/service/lane.go:432
github.com/polarismesh/polaris/service/interceptor/auth.(*Server).collectLaneRuleAuthContext
	/service/interceptor/auth/lane.go:128

问题 1 可通过创建带 metadata 的命名空间后查询验证:写入的 metadata 不会返回,数据库中该列为空。

问题 2、3、4 为 SQL 语句本身的错误,执行即报错。

Expected behavior

  • namespace 的 metadata 能够正常写入与读出,与 boltdb 实现保持一致
  • client_stat 相关语句使用正确的列名 client_id
  • BatchCleanDeletedClients 的占位符与参数数量一致,并按 timeout 过滤
  • auth_role_principal 的插入语句列名与占位符正确
  • LaneCache.GetRule 在 id 不存在时返回 nil 而非 panic

Environment

  • Version: main(df0ce073
  • OS: 与平台无关

Additional context

上述问题均在为 store 层适配 PostgreSQL 时,通过逐条执行 SQL 发现。PostgreSQL 侧已验证修复有效;MySQL 侧目前只跑了仓库内已有的单元测试(store/mysql 现有测试未覆盖这些路径),结论主要基于 SQL 语义与表结构的比对。

已准备好对应的修复,将提交 PR 关联本 issue。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions