0

テーブル T に新しい行を挿入するとき、テーブルが特定のしきい値よりも大きいかどうかを確認し、その場合は最も古いレコードを削除します (最終的にある種の FIFO を作成します)。

単純にトリガーを作成できると思っていましたが、MySQL では、実際に挿入しているテーブルの変更が許可されていないようです。

Code: 1442  Msg: Can't update table 'amoreAgentTST01' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

これが私が試したトリガーです:

Delimiter $$ 
CREATE TRIGGER test 
       AFTER INSERT ON amoreAgentTST01
       FOR EACH ROW
BEGIN
    DECLARE table_size INTEGER;
    DECLARE new_row_size INTEGER;
    DECLARE threshold INTEGER;
    DECLARE max_update_time TIMESTAMP;

SELECT SUM(OCTET_LENGTH(data)) INTO table_size FROM amoreAgentTST01;
SELECT OCTET_LENGTH(NEW.data) INTO new_row_size;
SELECT 500000 INTO threshold;
select max(updatetime) INTO max_update_time  from amoreAgentTST01;

IF (table_size+new_row_size) > threshold THEN
   DELETE FROM amoreAgentTST01 WHERE max_update_time = updatetime; -- and check if not current
END IF;
END$$
delimiter ;

データベース内でこれを行う方法について何か考えはありますか?

それとも、明らかに私のプログラムで行うべきことですか?

4

1 に答える 1

4

理想的には、オフピーク時に実行される別のプロセスで専用のアーカイブ戦略を用意する必要があります。

これは、スケジュールされたストアド プロシージャ (yuck)、アプリケーション サーバー内の追加のバックグラウンド ワーカー スレッド、または完全に別のアプリケーション サービスとして実装できます。これは、他の定期的なハウスキーピングの仕事を配置するのに適した場所です。

これにはいくつかの利点があります。発生しているトリガーの問題を回避することとは別に、トリガーで発生する何かのパフォーマンスへの影響を考慮する必要があります。多くの挿入を行う場合、そのトリガーはその作業を実行し、他のプロセスが同じテーブルにアクセスしようとするときに発生するロック競合は言うまでもなく、パフォーマンスを効果的に半分にします。

ハウスキーピング作業を行う別のプロセスにより、ロックの競合が最小限に抑えられ、トランザクション内で高性能の一括操作として作業を実行できます。

最後に、レコードを削除するのではなく、別のテーブルまたはデータベースにアーカイブすることを検討する必要があります。

于 2009-04-01T15:49:55.603 に答える