问题
I have an event in MySQL that I want to run very frequently at least every 30 seconds.
It is processing data from a queue table that contains recently updated records. Sometimes I receive large batches of updates. When this occurs the event may take longer to run than the usual 2-3 seconds. If it is still running at the time of the next schedule, I want the next event to skip execution.
The best way I could think about doing this is to create a 'state' table in which I set a specific key to 1 when the process starts, set it back to 0 when it is complete. I'd then alter the event to check the current status.
I'd prefer to do something nicer than that. Is there a feature I am missing completely?
I've looked into global variables but based on the documentation these only seem permissible for system variables.
Current Example Code
Here is the example code I'm currently testing.
acca_sync: BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE,
@errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
SET @full_error = CONCAT("ERROR ", @errno, " (", @sqlstate, "): ", @text);
call pa.log(concat("acca-acc_sync"," - Error - ", ifnull(@full_error, "no error message")));
UPDATE `acca`.`processing_state`
SET `value` = 0
WHERE `key` = 'acca_sync';
END;
call pa.log(CONCAT("Started acca_sync @ ", NOW()));
SELECT `value`
into @is_locked
from `acca`.`processing_state`
where `key` = 'acca_sync';
IF @is_locked = 0 THEN
UPDATE `acca`.`processing_state`
SET `value` = 1
WHERE `key` = 'acca_sync';
ELSE
CALL pa.log(CONCAT("acca_sync deferred due to active sync. @ ", NOW()));
LEAVE acca_sync;
END IF;
call acca.event_sync();
call pa.log(CONCAT("Completed acca_sync @ ", NOW()));
UPDATE `acca`.`processing_state`
SET `value` = 0
WHERE `key` = 'acca_sync';
END
Table Locking
Based on a comment I want to explain why I am not using a table lock. My experience with table locks is limited so I hope the below is correct and makes sense.
Source Data Tables
I have triggers that notify updates in queue tables. These are my source data tables from which I read data to process it.
My understanding is that a READ
lock on these tables would not lock any other events that just read.
If I was to use a WRITE
lock I would block any updates to any of the rows that I don't currently access.
Target Data Tables
I have multiple data sources that process data in different events. The rows these will amend in the target tables. There may be two different events running at the same time writing to the same table, so I don't artificially want to block the target tables
Other Tables
I could create a fake table that I would only have for the purpose of setting and then checking the existance of a lock. This seems absurd and I'd much rather instead create a single table locks with a lock_key
and an is_locked
column that I query each time.
回答1:
You can verify if is there any event running:
SELECT *
FROM performance_schema.threads
WHERE NAME LIKE '%event_worker%'
AND TYPE='FOREGROUND'
Other interesting table to watch:
SELECT * FROM information_schema.processlist
来源:https://stackoverflow.com/questions/38141988/can-i-avoid-two-mysql-events-running-at-the-same-time