web-dev-qa-db-ja.com

MySQLイベントが実行されない

windowsでxamppにバンドルされているmysql 5.1.41を実行しています。問題は、event schedulerONであっても、イベントが自動的に実行されないことです。 ta_tableという名前のテーブルがあり、innodb engineを使用して4つのフィールドがあり、そのうちの1つはti_timeで、timestampタイプはデフォルト値current timestampです。このフィールドti_timeには、行が挿入されるタイムスタンプの値が与えられます。 2時間経過したすべての行をテーブルta_tableから削除したいので、次のようなイベントを作成しました。

CREATE EVENT ev ON SCHEDULE EVERY 1 MINUTE STARTS 2011-07-17 14:54:52 ENABLE 
    DO
    begin
    delete from ta_table where timestampdiff(minute,ti_time,now())>120;
    end

このイベントにより、ti_timeフィールドが2時間(120分)より大きい行が削除されます。このクエリを実行すると

delete from ta_table where timestampdiff(minute,ti_time,now())>120;

できます。 2時間より古い行を削除します。つまり、私のクエリは正しいが、イベントは実行されていません。私のイベントスケジューラはshow processlistで確認したものを実行しており、2つの優先ルートとイベントスケジューラが表示されています。イベントスケジューラのstatewaiting for next activationです。このクエリを実行したとき

SELECT * FROM INFORMATION_SCHEMA.EVENTS WHERE event_name = 'ev'

結果は次のようになります

status = enabled
last executed=2011-07-18 02:36:38

しかし、テーブルta_tableを見ると、レコードは削除されていませんか?これでどうしたの?

編集:

RolandoMySQLDBAの提案の時点で、mysql 5.1.14をmysql 5.5にアップグレードしましたが、イベントはまだ失敗します

4
lovesh

イベントスケジューラの問題について、バグリストを実際に掘り下げました。

イベントスケジューラの特定の時間計算は移植できなかったようです 。このバグはMySQL 5.1.48で修正されました(2010年6月2日で修正)。

SHOW EVENTSが正しいデータベースからイベントを取得しないという過去の問題がありました 。このバグはMySQL 5.1.57(2011年5月5日修正)で修正されています。

最新のスケジューラのバグは、2011年7月5日にMySQL 5.1.58で修正されました

MySQL 5.1.41を使用しています。 MySQL 5.1の最新バージョンである5.1.58にアップグレードしたい場合があります 。現在のところ、スケジューラのバグはありません。

警告

別のメモでは、SQLクエリを変更して、作業量を減らすだけではありません

DELETEクエリの代わりに:

delete from ta_table where timestampdiff(minute,ti_time,now())>120;

次のように再構成します。

delete from ta_table where ti_time < (now() - interval 2 hour);

DELETEは、テーブルのすべての行に対して計算します。この新しいDELETEは、すべての行でtimestampdiffを計算する代わりに、ti_timeを時間値(now()-間隔2時間)と比較すると、短時間で停止します。

Ti_timeにインデックスが付けられていることを確認してください。そうでない場合は、次のようにします。

ALTER TABLE ta_table ADD INDEX (ti_time);

テーブルがMyISAMであると仮定すると、次のようにテーブルを毎月定期的に縮小することもできます。

ALTER TABLE ta_table ENGINE=MyISAM;

この情報がお役に立てば幸いです。

UPDATE 2011-07-19 08:00 EDT

最後のチャットルームセッションloveshと私が持っていた、MySQL 5.5.12を実行している私のPCでイベントを作成するために実行した例を次に示します。

drop database lovesh;
create database lovesh;
use lovesh
create table mydata (id int not null auto_increment primary key,ti_time timestamp DEFAULT current_timestamp) ENGINE=MyISAM;
DELIMITER $$
DROP PROCEDURE IF EXISTS `lovesh`.`LoadMyData` $$
CREATE PROCEDURE `lovesh`.`LoadMyData` ()
BEGIN
    DECLARE NDX INT;
    SET NDX = 0;
    WHILE NDX < 100 DO
        INSERT INTO mydata (ti_time) VALUES (NOW() - INTERVAL CEILING(14400*Rand()) SECOND);
    SET NDX = NDX + 1;
    END WHILE;
END $$
DELIMITER ;
show create table mydata\G
SHOW CREATE PROCEDURE LoadMyData\G
CALL lovesh.LoadMyData();
CREATE TABLE ta_table LIKE mydata;
ALTER TABLE ta_table DISABLE KEYS;
INSERT INTO ta_table SELECT SQL_NO_CACHE * FROM mydata;
ALTER TABLE ta_table ENABLE KEYS;
CREATE EVENT ev
    ON SCHEDULE
      EVERY 1 MINUTE
      STARTS (NOW() + INTERVAL 1 MINUTE)
    DO
      DELETE FROM ta_table WHERE ti_time > NOW() - INTERVAL 2 HOUR;
SELECT COUNT(1) FROM ta_table;
SELECT SLEEP(62);
SELECT COUNT(1) FROM ta_table;

Ta_tableがMyISAMだったとき、これは私のために働きました。 InnoDBを使用して実行を続けただけです。これが問題になるかもしれません。

5
RolandoMySQLDBA

あなたのイベントは完全修飾スキーマとテーブル名を使用して定義する必要があると思います:

MySQL 5.1.6では、イベントのアクションステートメントで参照されるテーブルは、それが発生するスキーマの名前(つまり、schema_name.table_name)で完全修飾する必要があります。

リファレンス: http://www.cs.duke.edu/csl/docs/mysql-refman/events.html#events-limitations-restrictions

したがって、EVENT内のクエリを再定義する必要があります(Rolandoの改良された削除クエリを使用):

DELETE FROM `ta_db`.`ta_table` WHERE ti_time < (NOW() - INTERVAL 2 HOUR);
3
Derek Downey