MySQL 触发器的坑:ERROR 1054 (42S22): Unknown column 'xxx' in 'field list'

更新日期: 2019-05-14 阅读次数: 32449 字数: 776 分类: MySQL

今天线上项目报错了 500 错误,Laravel 日志中显示

Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: 
Column not found: 1054 Unknown column 'is_charge' in 'field list' 
(SQL: update `some_categories` set `lft` = case when `lft` >= 29 then `lft`+2 else `lft` end, `rgt` = case when `rgt` >= 29 then `rgt`+2 else `rgt` end where (`lft` >= 29 or `rgt` >= 29))'

即新增层级菜单的时候,更新历史节点的 left right 值报错。

但是,报错很诡异,SQL 语句中并没有 is_charge 出现,但是却一直报

Column not found: 1054 Unknown column 'is_charge' in 'field list' 

这个错误很常见,以往都是因为线上数据表表没有同步新增字段,引起字段缺失。但是,完全不相关的 SQL 语句怎么会报出这个错误呢?

排除 Laravel 的问题

为了排除是 Laravel 的三方依赖问题,我直接在 MySQL 命令行中执行测试:

mysql> update some_categories set is_charge = 1 where id = 241;
ERROR 1054 (42S22): Unknown column 'is_charge' in 'field list'
mysql> update some_categories set type = 1 where id = 241;
ERROR 1054 (42S22): Unknown column 'is_charge' in 'field list'

果然,都是同样的错误,这么简单的 SQL 语句都会报错,说明不是单纯的 SQL 拼写错误。

我猜测是这个表有 MySQL 的触发器。

排查 MySQL 的触发器

SELECT * FROM information_schema.TRIGGERS \G;

果然找到了对应的触发器

TRIGGER_CATALOG: def
            TRIGGER_SCHEMA: db1
              TRIGGER_NAME: some_categories_insert
        EVENT_MANIPULATION: INSERT
      EVENT_OBJECT_CATALOG: def
       EVENT_OBJECT_SCHEMA: db1
        EVENT_OBJECT_TABLE: some_categories
              ACTION_ORDER: 1
          ACTION_CONDITION: NULL
          ACTION_STATEMENT: BEGIN INSERT INTO db2.some_categories (id,name,type,link,page_id,page_id,parent_id,lft,rgt,depth,image,created_at,updated_at,is_charge) VALUES (NEW.i$,NEW.name,NEW.type,NEW.link,NEW.page_id,NEW.parent_id,NEW.lft,NEW.rgt,NEW.depth,NEW.image,NEW.created_at,NEW.updated_at,NEW.is_charge);
END

问题很明显了,对应的同步数据库 db2 里的对应表,缺少了 is_charge 字段。确认了一下,确实如此。

问题解决。

参考:https://bugs.mysql.com/bug.php?id=68715

战斗还没有结束

新增字段之后,不报之前的错误了。但是又出现了一个新的错误。

[2019-05-13 22:47:49] production.ERROR: SQLSTATE[21S01]: 
Insert value list does not match column list: 
1136 Column count doesn't match value count at row 1
 (SQL: insert into `some_categories` (`name`, `parent_id`, `lft`, `rgt`, `updated_at`, `created_at`) values (测试测试, 225, 29, 30, 2019-05-13 22:47:49, 2019-05-13 22:47:49)) 

Column count doesn't match value count 这个错误也很容易理解,就是字段名列表跟值列表个数不匹配。检查了 SQL 没有问题,看来又是触发器的问题了。

在 MySQL 命令行下做了验证,确实如此

mysql> insert into some_categories (name, `type`) values ('test', 1);
ERROR 1136 (21S01): Column count doesn't match value count at row 1

晚上实在太困,到了凌晨,效率更低,愣是没看出触发器那里写错了字段。我决定先睡觉去。。。

今天一早,瞬间发现 page_id,page_id 写了两遍。。。

去掉一个之后,就恢复正常了。

结论

  • MySQL 排除 SQL 语句问题时,最好在 MySQL 命令行中进行。没有干扰。
  • 触发器确实少用比较好,容易忘掉他的存在
  • MySQL 的提示确实不够友好。没有注明是触发器中的问题。感觉想尝试其他数据库了。
  • 凌晨排查问题效率太低,不能指望人肉排查

关于作者 🌱

我是来自山东烟台的一名开发者,有敢兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式