PAYATHON 2026

GridDB 写入约 10MB STRING 报错 60079 的原因是什么?

数据小许

结论:10MB 超出文档中的 STRING 上限

GridDB 的 STRING 列值有大小限制,按 UTF-8 编码后的字节数计算。以 GridDB 5.7 官方文档为例,上限随数据库块大小变化:

数据库块大小单个 STRING 列值上限
64KB31KB
1MB、4MB、8MB、16MB、32MB128KB

这些限制针对单个字段值。即使块大小为 32MB,单个 STRING 也不能存储 32MB。上述数值来自 GridDB 5.7 Features Reference。实际环境只给出了“5.x”,还需对照具体小版本的文档。

约 10MB 的字符串超过了这些上限,写入失败符合超限情形。不过,同一份文档中的上限也低于约 1MB,因此还需单独核实“约 1MB 可以成功写入”的情况,不能据此推断 GridDB 的限制介于 1MB 和 10MB 之间。

60079 能否直接确定为字符串超限?

60079 DS_TIM_ROW_DATA_INVALID 表示行注册失败,列值超过允许范围是可能的原因之一。官方还要求检查实际 schema、客户端与服务端版本,以及字符串、BLOB、数组等数据的大小或取值范围。因此,这个错误码支持“字段超限”的判断,但不能单凭它确定具体是哪项限制。GridDB 错误码说明

在给出的代码中,payload 是最需要检查的字段。服务端与客户端版本相同,也不会取消 STRING 的容量限制。

先核实写入长度和实际 schema

在 container.put(row) 前记录字符数与 UTF-8 字节数:

import java.nio.charset.StandardCharsets;

byte[] bytes = payload.getBytes(StandardCharsets.UTF_8);
System.out.println("UTF-16 code units: " + payload.length());
System.out.println("UTF-8 bytes: " + bytes.length);

示例中的字符串完全由 ASCII 字符 A 组成,1_000_000 个字符对应 1_000_000 个 UTF-8 字节,10_000_000 个字符对应 10_000_000 个 UTF-8 字节。中文等内容的字节数可能不同,不能统一用 String.length() 判断是否超限。

然后按以下顺序排查:

  1. 确认服务端和实际加载的 Java client JAR 的完整版本号。
  2. 使用 store.getContainerInfo(containerName) 检查服务端已有容器的列名、列顺序和类型,确认 payload 确实为 GSType.STRING。
  3. 检查写入目标集群、数据库与容器名称,确认两次测试使用同一环境,且写入前没有截断或转换数据。
  4. 若关闭了自动提交,确认已成功执行 commit(),再从数据库读回数据,比较完整长度和内容。
  5. 保存完整异常及对应的服务端日志。若约 1MB 的 STRING 仍能稳定写入并完整读回,应结合具体版本继续调查,现有材料不足以解释这一差异。

大文本可改用 BLOB

如果需要整体存储和读取约 10MB 的文本,可以将 UTF-8 字节保存为 BLOB。GridDB 5.7 文档列出的 BLOB 上限为 1GB - 1Byte;这只是类型上限,实际写入仍受内存、通信和超时等条件影响。GridDB 数据类型限制

下面的示例假设 store 已连接、payload 已生成,并使用一个新的容器名称。新容器的第二列为 GSType.BLOB:

import com.toshiba.mwcloud.gs.*;
import java.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.util.Arrays;

ContainerInfo info = new ContainerInfo();
info.setType(ContainerType.COLLECTION);
info.setColumnInfoList(Arrays.asList(
    new ColumnInfo("id", GSType.STRING),
    new ColumnInfo("payload", GSType.BLOB)
));
info.setRowKeyAssigned(true);

try (Container<String, Row> blobs =
         store.putContainer("payload_blob", info, false)) {
    blobs.setAutoCommit(true);
    byte[] bytes = payload.getBytes(StandardCharsets.UTF_8);
    Blob blob = blobs.createBlob();
    try {
        blob.setBytes(1L, bytes);

        Row row = blobs.createRow();
        row.setString(0, "device-1");
        row.setBlob(1, blob);
        blobs.put(row);
    } finally {
        blob.free();
    }
}

Container.createBlob()、Blob.setBytes() 和 Row.setBlob() 的用法见 GridDB Java API Reference。读取时用相同的 UTF-8 编码恢复字符串。

调整方案时的注意事项

  • 已有 STRING 列不会因为调用 setBlob() 自动变成 BLOB。应创建符合新 schema 的容器,并安排数据迁移。
  • BLOB 适合保存完整内容。如果需要对文本内容做筛选或搜索,应另存用于查询的字段。
  • STRING、UTF-8 字节数组和 BLOB 的处理过程会占用内存,应以实际负载验证资源需求。
  • 增大块大小仍无法让上述 STRING 上限达到 10MB。storeBlockSize 也是数据库结构参数,不能在首次启动后随意修改,详见 GridDB 参数说明。

备注:内容仅供参考。