【问题标题】:Concurrent UPDATE's on MySQL TRIGGERMySQL TRIGGER 上的并发更新
【发布时间】:2025-11-21 23:05:01
【问题描述】:

我在 MySQL 中有这个触发器:

CREATE DEFINER = CURRENT_USER TRIGGER `test`.`view_AFTER_INSERT` AFTER INSERT ON `views` FOR EACH ROW
BEGIN
UPDATE metrics SET met_nu_vie = met_nu_vie + 1 WHERE usp_id = NEW.usp_id;   
END

基本上,当用户在 Web 应用程序中收到另一个用户的“视图”时,系统会在表“视图”中创建一个新行,并在插入后增加另一个表中的计数器值(指标)。

我的问题是:如果用户收到来自 10 个不同用户的 10 个并发视图...¿这个 UPDATE 安全吗?

我的架构上的所有表都是 INNODB。

谢谢。

【问题讨论】:

    标签: mysql


    【解决方案1】:

    如果用户收到 X 个并发视图,则计数器会随着问题中的更新语句增加 X。

    正如innodb locks 上的 mysql 手册所解释的:

    UPDATE ... WHERE ... 为每条记录设置一个独占 next-key lock 搜索遭遇。但是,只需要一个索引记录锁 for 使用唯一索引锁定行以搜索 唯一的行。

    Mysql 排他锁手册说:

    如果事务 T1 在行 r 上持有排他 (X) 锁,则请求 从某个不同的事务 T2 获取r 上任一类型的 [独占或共享] 锁 不能立即授予。相反,事务 T2 必须等待 事务 T1 释放其对行 r 的锁定。

    总结一下:查看器在您的应用程序级别可能是并发的,但在 mysql 级别更新是使用排他锁序列化的。

    【讨论】:

    • 谢谢影子。但我有一个疑问:在这个页面,dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html,有一个增加表中计数器的示例:SELECT counter_field FROM child_codes FOR UPDATE;更新 child_codes SET counter_field = counter_field + 1;我的解决方案与这个不同吗?我不需要使用 SELECT... FOR UPDATE 吗?
    • 不,您不必这样做。您正在使用原子更新。这只是一个例子。在另一个类似但更通用的问题中查看答案(不仅仅是我的!):*.com/questions/37557110/…