I did some real digging in the bug list for event scheduler issues.
It seems that a certain time calculation for the event scheduler was not portable. This bug was fixed as of MySQL 5.1.48 (Fixed June 2, 2010).
There was a past issue about SHOW EVENTS not getting events from the correct database. This bug was fixed as of MySQL 5.1.57 (Fixed May 5, 2011).
The latest scheduler bug was fixed July 5, 2011 in MySQL 5.1.58
You are using MySQL 5.1.41. You may want to upgrade to the latest version of MySQL 5.1 which is 5.1.58. No scheduler bugs exists as of today.
CAVEAT
On another note, I would change the SQL query to not only do less work
Instead of your DELETE query:
delete from ta_table where timestampdiff(minute,ti_time,now())>120;
Restructure it as follows:
delete from ta_table where ti_time < (now() - interval 2 hour);
Your DELETE will calculate against every row in the table. This new DELETE stops short when comparing ti_time against a time value (now() - interval 2 hour) instead of computing timestampdiff on every row.
Make sure ti_time is indexed. If not, do this:
ALTER TABLE ta_table ADD INDEX (ti_time);
Assuming the table is MyISAM, you may also want to periodically shrink the table every month like this:
ALTER TABLE ta_table ENGINE=MyISAM;
I hope this information helps !!!
UPDATE 2011-07-19 08:00 EDT
From the last chat room session lovesh and I had, here is the example I ran to create the event on my PC running MySQL 5.5.12:
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;
This worked for me when ta_table was MyISAM. It just kept running using InnoDB. This may be the sticking point.
You can't directly do it since there's no way (that I can think of) to alternately UPDATE
or DELETE
from the same query... generally a query can only do one type of CRUD operation (ON DUPLICATE KEY UPDATE
being an exception to this).
You could, however, make it "feel like" a single query, with a stored procedure, where you'd set up a CONTINUE HANDLER
for the foreign key error you anticipate. The handler will trap the error and can be used to set a variable which you can test to see whether you hit the error and therefore need to also try the update query.
DELIMITER $$
DROP PROCEDURE IF EXISTS delete_or_update $$
CREATE PROCEDURE delete_or_update (IN input_value INT)
BEGIN
DECLARE hit_fk_error TINYINT DEFAULT 0;
DECLARE deleted_row_count INT DEFAULT NULL;
DECLARE updated_row_count INT DEFAULT NULL;
-- 1451 is probably the error code that will be generated
-- Cannot delete or update a parent row: a foreign key constraint fails (%s)
-- otherwise, you may need to substitute the correct error code in the next line
DECLARE CONTINUE HANDLER FOR 1451 SET hit_fk_error = TRUE;
DELETE FROM parent_table WHERE tested_column = input_value; /* arg to the stored proc */
SET deleted_row_count = ROW_COUNT();
IF (hit_fk_error = TRUE) THEN
UPDATE parent_table SET some_other_value = 'something_else'
WHERE tested_column = input_value;
SET updated_row_count = ROW_COUNT();
END If;
SELECT deleted_row_count, updated_row_count, hit_fk_error;
END $$
DELIMITER ;
This will try the delete; if it hits a foreign key error it will then try the update (and the foreign key error will be suppressed). The procedure will return a record set with the number of rows affected by each query and whether the foreign key error occurred. If the "input_value" isn't an INT
or the WHERE
clause is more complex, you'll need to modify the structure, accordingly.
The potential problem I see here is that if the where clause is too broad, and matches some rows that would cause a foreign key error and other rows that wouldn't, then the query will not treat the rows individually. That could be accomplished by a more sophisticated procedure that used a cursor to find the rows in the where clause and tried to delete or update them individually by primary key after identifying them. That approach would be less efficient but more precise.
Best Answer
To fix the syntax error:
That won't land on midnight. Instead change to:
Give writing the EVENT a try.
Be sure to do (once):