MySQL(Aurora-MySQL)中CONCAT函数支持的字符串最大长度是多少
我当前在基于MySQL 5.7.x的Aurora MySQL中运行一个PROCEDURE,它接收ID序列化列表作为TEXT类型的入参,使用CONCAT函数拼接生成预处理语句执行。
该存储过程大部分时候运行正常,但少数调用会触发截断错误,报错信息如下:
com.mysql.jdbc.MysqlDataTruncation Data truncation: Data too long for column 'stuffIds' at row 1
我最初以为是存储过程的stuffIds参数类型容量过小,检查后发现其类型为TEXT,我原本误以为TEXT的上限是2^31字符(即2GB数据),我们的业务场景中不可能有如此多的ID达到该上限。
之后我猜测问题可能和拼接预处理语句用到的CONCAT函数有关?但我只查到很多关于GROUP_CONCAT最大长度及相关配置的问题与解答,没有找到MySQL CONCAT函数支持的字符串最大长度的相关说明。
我最后怀疑是不是AWS Aurora的MySQL实现特有的问题?我了解Aurora和原生MySQL的实现高度接近,但会不会是这个边缘场景存在差异?
触发报错的PROCEDURE代码如下(标识符已做脱敏处理):
DELIMITER // CREATE PROCEDURE GetThingsByStuffIds(stuffIds TEXT) BEGIN SET @stmt = CONCAT('SELECT ThingId FROM ThingTable WHERE StuffId IN (', stuffIds, ')'); PREPARE insert_stm FROM @stmt; EXECUTE insert_stm; DEALLOCATE PREPARE insert_stm; END // DELIMITER ;
我此前对MySQL TEXT类型的长度认知有误:我原本以为其上限是2^31字符(或2GB数据),这部分认知完全错误。
和PostgreSQL不同,MySQL的TEXT有三种容量变体:
TEXT:最大65535字符MEDIUMTEXT:最大16777215字符LONGTEXT:最大4294967295字符
我之前误解了TEXT的长度上限,所以才会出现调用超出限制的问题,补充该提示避免错误认知误导其他人。
核心原因
报错的根本原因就是传入的ID序列化列表长度超出了TEXT类型的容量上限,和CONCAT函数、Aurora的定制实现没有关联。
MySQL中普通TEXT类型的最大存储长度为65535字节,若使用多字节字符集(比如常用的utf8mb4),可存储的字符数会低于65535,当传入的ID列表长度超过阈值时就会触发数据截断错误。
解决方案
- 直接调整参数类型:将存储过程的
stuffIds入参类型从TEXT替换为MEDIUMTEXT或LONGTEXT即可解决容量不足的问题,MEDIUMTEXT最大支持16MB存储,LONGTEXT最大支持4GB存储,完全可以满足绝大多数业务场景的长ID列表需求。 - 额外优化建议:当前通过拼接SQL实现IN查询的方式存在SQL注入风险,同时超大的IN列表也会带来查询性能下降的问题,建议可根据业务情况选择用临时表存储ID列表后关联查询、或者拆分大批次ID分批查询的方案,进一步提升安全性和稳定性。
内容的提问来源于stack exchange,提问作者cjn

