为什么SQL触发器中不能使用所有聚合函数来维护数据库事务和一致性?

2026-04-27 21:280阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计806个文字,预计阅读时间需要4分钟。

为什么SQL触发器中不能使用所有聚合函数来维护数据库事务和一致性?

简化版开头内容,无需试图解答案,不要数落,不超过100字,直接输出结果:

触发器是行级同步执行,聚合函数却是表级扫描

每次 INSERT/UPDATE/DELETE 一行,触发器就跑一次。如果里面写 SUM()COUNT() 或子查询套聚合,等于每行都触发一次全表扫描——比如在订单表的 AFTER INSERT 里查 SELECT SUM(amount) FROM orders WHERE user_id = NEW.user_id,1000 个订单插入就要扫 1000 次用户订单记录。

  • MySQL 的 InnoDB 在这种场景下极易出现 Lock wait timeout exceededDeadlock found when trying to get lock
  • PostgreSQL 会卡在 SHARE ROW EXCLUSIVE 锁上,尤其当聚合查询没走索引时
  • 即使加了索引,高并发下多个触发器同时读同一张汇总表,也会争抢 consistent read 版本,拖慢主事务

NEW 和 OLD 是快照,聚合结果却要实时算

触发器能直接用 NEW.amountOLD.status,因为它们是内存里的变更前/后值,零开销。但 SELECT AVG(x) FROM t WHERE y = NEW.y 是实打实去磁盘捞数据,还可能被其他事务正在改的行阻塞。

阅读全文
标签:聚合函数

本文共计806个文字,预计阅读时间需要4分钟。

为什么SQL触发器中不能使用所有聚合函数来维护数据库事务和一致性?

简化版开头内容,无需试图解答案,不要数落,不超过100字,直接输出结果:

触发器是行级同步执行,聚合函数却是表级扫描

每次 INSERT/UPDATE/DELETE 一行,触发器就跑一次。如果里面写 SUM()COUNT() 或子查询套聚合,等于每行都触发一次全表扫描——比如在订单表的 AFTER INSERT 里查 SELECT SUM(amount) FROM orders WHERE user_id = NEW.user_id,1000 个订单插入就要扫 1000 次用户订单记录。

  • MySQL 的 InnoDB 在这种场景下极易出现 Lock wait timeout exceededDeadlock found when trying to get lock
  • PostgreSQL 会卡在 SHARE ROW EXCLUSIVE 锁上,尤其当聚合查询没走索引时
  • 即使加了索引,高并发下多个触发器同时读同一张汇总表,也会争抢 consistent read 版本,拖慢主事务

NEW 和 OLD 是快照,聚合结果却要实时算

触发器能直接用 NEW.amountOLD.status,因为它们是内存里的变更前/后值,零开销。但 SELECT AVG(x) FROM t WHERE y = NEW.y 是实打实去磁盘捞数据,还可能被其他事务正在改的行阻塞。

阅读全文
标签:聚合函数