问题现象

普通 SQL 正常,stg 环境没发现异常。但生产环境用户反馈:超长 SQL(超过 1MB)会触发 400 报错

恰好生产环境的用户有很多那种业务逻辑复杂、拼接出来的超长 SQL。

排查过程

第一步是对比。把报错的 SQL 和不报错的 SQL 摆在一起看,唯一的共同点就是——

短 SQL 跑得好好的,长到一定长度就 400。这不是 SQL 语法问题,是传输层的问题。

根因

查到最后,原因是这样的:

  1. 安全合规要求,把普通的 Statement 升级为 PreparedStatement。因为普通 Statement 有 SQL 注入风险,安全团队要求整改。
  2. Presto 驱动版本太低,低版本的 Presto JDBC 驱动对 PreparedStatement 的支持不完善,特别是对超长 SQL 的处理有 bug。
  3. 服务端 Presto 没有同步升级。原因很简单——影响太大,涉及的下游服务和业务太多,不敢动。

所以就出现了一个尴尬的局面:客户端驱动升级了(为了安全),服务端没升级(为了稳定),两边版本不一致,超长 SQL 直接 400。

解决方案

还原升级。

把客户端驱动退回到兼容当前服务端的版本。安全问题用其他方式规避(比如在应用层做参数化查询、输入校验等)。

这不是最优解,但在"安全"和"可用"之间,先保可用。

避坑建议

1. 灰度环境重点覆盖验证

stg 环境为什么没发现?因为测试用的 SQL 都是短的。灰度环境应该重点覆盖边界场景

  • 超长 SQL(1MB+)
  • 特殊字符
  • 高并发场景

2. 客户端和服务端版本要对齐

升级驱动前,先确认服务端版本兼容性。不要客户端升了、服务端没升,两边版本不一致是定时炸弹。

3. 安全整改要评估影响面

安全团队要求升级 Statement → PreparedStatement,这个决策本身没问题。但执行前应该评估:

  • 当前 Presto 驱动版本是否支持
  • 服务端是否需要同步升级
  • 影响的业务范围

4. SQL 长度监控

在应用层加 SQL 长度监控和告警。不是所有用户都会写短 SQL,业务复杂度上去了,SQL 就会变长。提前发现比线上报错强。

总结

这个事故的教训:

  • 版本对齐比什么都重要,客户端和服务端不要各升各的
  • stg 测试要覆盖生产真实场景,不能只测"正常路径"
  • 安全和稳定要平衡,不能为了安全把生产搞挂了

相关技术:Presto JDBC、PreparedStatement、SQL 注入防护