-1

我正在使用下面显示的触发器自动为插入的行分配随机键,如果找到现有行,则重试随机生成。99.9% 的时间这完全符合预期。然而,每隔几周左右,触发器就会锁定,其中的REPEAT循环显然会变得无限;查询无限期地继续,有效地锁定了应用程序,并且必须被KILL编辑。

据我所见,所涉及的逻辑没有任何东西使这似乎应该发生。所涉及的密钥空间肯定不会耗尽,而且永远不会耗尽。到底是怎么回事?

触发:

DELIMITER //;
CREATE TRIGGER `mytable_insert` BEFORE INSERT ON `mytable`
FOR EACH ROW
BEGIN
    DECLARE `curr` BIGINT UNSIGNED;
    DECLARE `sel` BIGINT UNSIGNED;
    IF NEW.`mykey` IS NULL THEN
        REPEAT
            SELECT FLOOR(RAND() * 18446744073709551615) INTO `sel`;
            SELECT `id` INTO `curr` FROM `mytable` WHERE `mykey` = `sel` LIMIT 1;
        UNTIL `curr` IS NULL END REPEAT;
        SET NEW.`mykey` = `sel`;
    END IF;
END
4

1 回答 1

2

错误是这一行

SELECT `id` INTO `curr` FROM `mytable` WHERE `mykey` = `sel` LIMIT 1;

如果没有行匹配mykey = sel,则根本不分配 curr 。因此,如果 curr 曾经分配过其他任何东西,它就永远不会为空。

用这样的东西替换(未经测试)

DELIMITER //;
CREATE TRIGGER `mytable_insert` BEFORE INSERT ON `mytable`
FOR EACH ROW
BEGIN
    DECLARE `count` INT UNSIGNED;
    DECLARE `sel` BIGINT UNSIGNED;
    IF NEW.`mykey` IS NULL THEN
        REPEAT
            SELECT FLOOR(RAND() * 18446744073709551615) INTO `sel`;
            SELECT count(1) INTO `count` FROM `mytable` WHERE `mykey` = `sel`;
        UNTIL `count` = 0 END REPEAT;
        SET NEW.`mykey` = `sel`;
    END IF;
END
于 2012-05-26T05:13:23.200 回答