为什么这个触发器使我的一些插件挂起?

时间:2012-10-22 12:07:20

标签: mysql triggers

触发器如下:

DELIMITER //
CREATE TRIGGER `Conturi_BI` BEFORE INSERT ON `Conturi` FOR EACH ROW BEGIN
SET NEW.CUI_cod = digits(NEW.CUI);
END//
DELIMITER ;

我只是将数字函数应用于用户输入以便更快地匹配和重复搜索,但自从我实现它之后,我的一些插入就会挂起。我做了一个类似的更新,它没有相同的问题。

数字功能由我创建,触发器和插入功能在大多数情况下都能正常工作。

数字功能,根据要求:

BEGIN
  DECLARE i, len SMALLINT DEFAULT 1;
  DECLARE ret CHAR(32) DEFAULT '';
  DECLARE c CHAR(1);
  SET len = CHAR_LENGTH( str );
  REPEAT
    BEGIN
      SET c = MID( str, i, 1 );
      IF c BETWEEN '0' AND '9' THEN 
        SET ret=CONCAT(ret,c);
      END IF;
      SET i = i + 1;
      END;
  UNTIL i > len END REPEAT;
  RETURN ret;
END

2 个答案:

答案 0 :(得分:2)

如果您将digit传递给null,则select digits(null) 功能不起作用。它将永远循环。尝试使用

NEW.CUI

因此每次null为null时,它都会使您的插入挂起。您可以在函数开头添加if str is null then return ''; end if; 项检查:

{{1}}

答案 1 :(得分:1)

我最好的猜测是,从你的“某些”陈述来判断,lock contention会出现问题。

如果我理解你的触发器,在(实际上在)写入表A之前触发你的过程,这反过来改变了写入的同一个表中的每条记录,专门锁定单个事务中的每一行。

在另一个事务中执行此操作很可能导致deadlock情况,您的触发器等待升级锁定,另一个事务等待您完成锁定(简而言之,如果您愿意,则会出现死锁)。

这项努力的成功至少取决于数据库驱动程序的实现。锁定一行,然后在触发的事务中再次将其锁定大多数数据库驱动程序都假定事务可以加宽,但是,某些数据库无法看到事务来自同一连接并单独处理它们。