TDR 表数据读写与版本兼容性
本文聚焦 TDR 表两个易出问题但又常被忽略的兼容性主题:写入接口配对(SetData/SetValue)、跨实例 TDR 元数据版本兼容。这两点是 TDR 表特有的(PB 表无此问题)。
1. SetData 与 SetValue 的区别
TDR 表的 SDK 提供两种数据读写方式,必须配套使用:
- SetData / GetData:整条记录按 TDR 编解码,复杂类型字段(struct / union / 数组)自动在字段数据前附加 2 字节 TDR 版本号。
- SetValue / GetValue:按字段名逐字段读写原始 buffer,后端不做 TDR 编解码。
混用的后果:
- SetData 写入 + GetValue 读取:复杂类型字段的原始 buffer 包含 2 字节 TDR 版本头,GetValue 会原样返回,业务如果不知道需要跳过这 2 字节,会导致数据解析错误。
- SetValue 写入 + GetData 读取:SetValue 写入的 buffer 不含 TDR 版本头,GetData 尝试按 TDR 格式解包时,会因缺少版本头而解包失败或数据错乱。
2. TDR 表版本兼容
在普通 SetData / GetData 读写路径上,后端不校验 TDR 数据版本与本端元数据版本是否一致,版本兼容性需业务自行保证。
典型问题场景:GameSvr-A 使用 v+1 版本 TDR 元数据通过 SetData 写入数据,GameSvr-B 本地 TDR 元数据为 v 版本,通过 GetData 读取时会因版本不兼容导致 TDR 解包失败。
建议:业务修改 TDR 表结构时,确保所有接入的 GameSvr 同步更新 TDR 元数据。
3. TDR 表条件过滤与条件更新
条件过滤(condition)和条件更新(operation)适用于 SetData / GetData 方式。其原理是:后端需要按 TDR 协议解包字段数据才能判断条件、执行 PUSH / SET / POP 等数组操作;SetData 写入的数据带有完整的 TDR 编码(包含复杂类型字段头部的 2 字节版本号),因此后端能正确解包并参与条件过滤/更新。
- 条件过滤:支持 SQL 风格的条件表达式。若条件涉及嵌套字段(如
a.b.c > 1),后端需要对相应的复杂类型字段做 TDR 解包,因此要求存储数据与本端 TDR 元数据版本兼容。 - 条件更新(Operation):支持对数组字段的 PUSH / SET / POP 操作,包括一级数组字段和嵌套结构体内的数组字段(如
single_struct.sub_array)。同样要求存储数据与本端 TDR 元数据版本兼容。
关于 SetValue 写入的数据:
- 一级标量字段(如
int、string)SetValue 写入后仍然可以被条件过滤命中,因为标量字段不带 2 字节 TDR 版本头,后端按字段名直接读取原始 buffer 即可判断。 - 复杂类型字段(结构体、union、数组)SetValue 写入的 buffer 缺少 2 字节版本头,后端按 TDR 解包时会失败或拿到错乱的数据,不建议对 SetValue 写入的复杂字段使用条件过滤/数组更新;如需使用,请改走 SetData 写入路径。
完整的能力清单、命令矩阵、TDR vs PB 差异、性能优化等详情见《条件过滤和更新功能》。
4. 相关文档
- 《条件过滤和更新功能》
- 《条件过滤和更新语法说明》
- 《TDR 表 string 类型多语言兼容性》
- 《典型技术问题》§1:两 GameSvr 字段集不同时的 cross-write 行为(与 §2 不同维度)