Swoole 4 Table 字符串字段长度按字节计,64 字节列最多存 63 字节有效内容(UTF-8 中约 21 个汉字),超长写入会静默截断且无提示;需用 strlen 或 mb_strlen('8bit') 校验字节长度并预截取。

Swoole 4 的 Table 内存表中,字符串字段的长度设置是按字节而非字符计数的,写入超长数据时会静默截断——这是底层内存布局决定的行为,不是 bug,但极易被误用。
字符串字段的 size 是字节数,不是字符数
定义列时:$table->column('name', Swoole\Table::TYPE_STRING, 64) 中的 64 表示固定分配 64 字节内存,包含末尾的 \0 终止符,实际最多存 63 字节有效内容。
- UTF-8 编码下,1 个中文占 3 字节 → 64 字节最多存 21 个汉字(21×3=63)
- 英文、数字、ASCII 字符占 1 字节 → 最多存 63 个字符
- 混合内容需按实际字节计算,不能只看字符个数
超长写入一定会被截断,且无警告
调用 $table->set('key', ['name' => '超长字符串...']) 时,若值字节长度超过列定义的 size,Swoole 底层直接截取前 size - 1 字节(留 1 字节给 <p>调用 <code>$table->set('key', ['name' => '超长字符串...']) 时,若值字节长度超过列定义的 size,Swoole 底层直接截取前 size - 1 字节(留 1 字节给 \0),不会报错、不抛异常、不记录日志。
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
- 例如:
column('tag', TYPE_STRING, 5),写入'hello world'(11 字节)→ 实际存入'hell'(4 字节 +\0) - 这种截断发生在 C 层 memcpy 阶段,PHP 层完全感知不到
- 调试时用
get()拿到的数据就是已被截断的结果
如何安全控制字符串长度
避免意外截断,建议在写入前主动校验和处理:
- 用
mb_strlen($str, '8bit')或strlen($str)获取真实字节长度,与列 size 比较 - 写入前用
mb_substr($str, 0, $max_bytes, '8bit')截取字节,确保不溢出 - 对用户输入或外部来源的字符串,尤其要防范 UTF-8 多字节字符混入
- 开发期可在 set 前加日志:当
strlen($val) >= $defined_size时告警
注意 size 还影响整行内存和总容量
每列的 size 直接累加为单行大小(item_size),进而限制最大可存行数:
-
TYPE_INT的 size 只能是 1/2/4/8,设成 3 或 5 会被静默修正为 4 -
TYPE_FLOAT固定占 8 字节,size参数被忽略 - 所有列 size 总和 × 行数 > 128MB →
create()失败,报 “unable to allocate memory”

















