MySQL触发器触发STATE列数据过长错误 如何解决?
首先,咱们拆解下问题核心:你的触发器在MySQL 5.6.25-log环境触发Data truncation: Data too long for column 'STATE'错误,但在5.6.36和5.7.17中正常。本质原因是不同MySQL小版本里INFORMATION_SCHEMA.PROCESSLIST的列定义或内部处理逻辑存在差异——尽管你只查询了info字段,但5.6.25版本处理PROCESSLIST查询时,会默认读取所有列的完整内容,当当前连接的STATE字段内容超过该版本的长度限制时,就会触发截断错误。
下面给出几个可行的解决思路,按优先级排序:
1. 手动构造更新语句(最推荐)
依赖PROCESSLIST获取原SQL的方式本身就不稳定——触发器上下文里的info字段内容可能因版本、配置不同而变化,甚至可能为空。更可靠的方式是根据OLD和NEW的值手动拼接需要记录的SQL语句:
修改触发器中的INSERT部分:
INSERT INTO `update_commands`(`origin_id`, `origin_table_name`, `edited_by`, `command`) VALUES ( NEW.id, 'source_draft', NEW.last_edited_by, -- 手动构造去掉_draft后缀的更新语句,用QUOTE函数避免SQL注入风险 CONCAT('UPDATE source SET name = ', QUOTE(NEW.name), ' WHERE id = ', NEW.id) );
这种方式完全避开了PROCESSLIST的依赖,不存在版本兼容问题,同时也更安全。
2. 改用Performance Schema获取当前语句
如果一定要保留“获取原SQL”的逻辑,可以替换INFORMATION_SCHEMA.PROCESSLIST为performance_schema.threads表——它的PROCESSLIST_INFO字段是TEXT类型,没有长度限制,且在5.6版本中已经可用:
SET original_query = ( SELECT PROCESSLIST_INFO FROM performance_schema.threads WHERE PROCESSLIST_ID = CONNECTION_ID() );
注意:需要确保生产环境的performance_schema已启用。可以执行SHOW VARIABLES LIKE 'performance_schema';检查,如果值为OFF,需要在my.cnf(或my.ini)中添加performance_schema=ON,然后重启MySQL服务。
3. 临时规避:优化PROCESSLIST查询
如果你暂时无法修改配置或重构逻辑,可以尝试修改PROCESSLIST的查询语句,强制仅返回需要的字段,减少服务器的处理压力:
SET original_query = ( SELECT info FROM INFORMATION_SCHEMA.PROCESSLIST WHERE id = CONNECTION_ID() LIMIT 1 );
不过这个方法只是临时规避,无法从根本上解决版本兼容问题,不推荐长期使用。
最后额外提一句:检查下触发器里的第二个操作update source2_draft set name = NEW.name where name = OLD.name;,确保source2_draft表没有递归触发的触发器(虽然其他环境正常,但生产环境的配置可能存在差异)。
内容的提问来源于stack exchange,提问作者Elyran




