对于学校作业,我需要有一个包含80至100行(含)的MySQL表。 Cron作业每2小时在表格中输入一行。我想使用触发器来做到这一点,但是显然这是不可能的,因为该表由于INSERT语句而被锁定。这是我使用的触发器:

CREATE TRIGGER too_many_rows
BEFORE INSERT ON log
FOR EACH ROW
BEGIN
    IF (SELECT COUNT(id) FROM log) >= 100 THEN
        DELETE FROM log LIMIT 1;
    END IF;
END


棘手的是,表上也有手动插入,这就是为什么我不能定期检查(CRON作业或MySQL事件)表是否太多的原因,因为在某个时刻可能有太多的行。理想的情况是每次添加新行时都删除最旧的行。

有什么办法我仍然可以这样做吗?

最佳答案

您不能使用触发器来执行此操作。我会使用从应用程序代码调用的事务来做到这一点。

BEGIN;
INSERT INTO log ...;
SELECT id INTO @id FROM log ORDER BY id DESC LIMIT 1 OFFSET 100;
DELETE FROM log WHERE id <= @id;
COMMIT;


如果表中的行数少于100,则它将为@id分配NULL,而DELETE将不删除任何行。

如果表中有多于100行,它将从末尾开始向@id分配行的ID。然后,DELETE将删除该行和所有之前的行,仅保留100行。使用此多步方法比仅删除id
如果您有多个客户端同时执行,则为race condition。也就是说,两个并发会话可能同时处于选择和删除状态。这可能导致总行数暂时超过100,至少直到下一次插入行并删除多余的行为止。

10-07 13:18
查看更多