MySQL表必须包含80到100行

问题描述 投票:0回答:2

对于学校作业,我需要一个包含80到100行(包括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事件)是否有太多表,因为在某些时候可能有太多行。理想的情况是每次添加新行时删除最旧的行。

有什么办法我还能这样做吗?

mysql triggers mariadb
2个回答
1
投票

您无法使用触发器执行此操作。我会用从应用程序代码调用的事务来完成它。

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分配从末尾开始的100行的id。然后DELETE将删除该行和任何早期行,只留下100行。使用这种多步法比删除id <max - 100更好,因为你不应该假设没有丢失的id值。

如果你有多个客户同时这样做,那就有一个race condition。也就是说,两个并发会话可能都会被选择和删除。这可能导致总行数暂时超过100,至少在下一次插入行并删除额外行之前。


0
投票

似乎我正在寻找的是不可能的,所以我使用MySQL事件每小时删除多余的行。

这是代码:

EVENT check_for_redundant_rows

SET GLOBAL event_scheduler = ON;

DELIMITER $$

CREATE EVENT check_for_redundant_rows
ON SCHEDULE EVERY 1 HOUR
STARTS '2018-01-01 00:00:00'
DO
CALL delete_redundant_rows();
$$

DELIMITER ;

程序delete_redundant_rows()

DELIMITER $$

CREATE PROCEDURE delete_redundant_rows()
BEGIN
    DECLARE cnt INT DEFAULT 0;

    SELECT COUNT(id)
    INTO cnt
    FROM log;

    SET cnt = cnt - 80;

    DELETE FROM log
    ORDER BY id ASC
    LIMIT cnt;
END
$$

DELIMITER ;
© www.soinside.com 2019 - 2024. All rights reserved.