-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 は決して null にはなりません。

このようなものに置き換えます(未テスト)

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 に答える