我在MySQL中有一个事件,我希望至少每30秒运行一次。
它正在处理包含最近更新记录的队列表中的数据。有时我会收到大批量的更新。发生这种情况时,事件可能需要比通常的2-3秒更长的时间。如果它仍然在下一个计划时运行,我希望下一个事件跳过执行。
我能想到这样做的最好方法是创造一个“状态”。在进程启动时将特定键设置为1的表,在完成时将其设置为0。 然后我改变事件以检查当前状态。
我更喜欢做比这更好的事情。是否有我完全遗漏的功能?
我查看了全局变量,但根据文档,系统变量似乎只允许这些变量。
当前示例代码
以下是我目前正在测试的示例代码。
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
表格锁定
基于评论我想解释为什么我没有使用表锁。我对表锁的经验有限,所以我希望下面的内容是正确的,也是有道理的。
源数据表
我有触发器通知队列表中的更新。这些是我的源数据表,我从中读取数据来处理它。
我的理解是这些表上的READ
锁定不会锁定刚读取的任何其他事件。
如果我要使用WRITE
锁定,我会阻止对我目前无法访问的任何行的任何更新。
目标数据表
我有多个数据源可以处理不同事件中的数据。这些行将在目标表中修改。可能有两个不同的事件在同一时间写入同一个表,因此我不会人为地想要阻止目标表
其他表格
我可以创建一个假表,我只能设置然后检查锁的存在。这似乎很荒谬,而且我更愿意创建一个包含lock_key
和is_locked
列的表锁,我每次都会查询。
答案 0 :(得分:0)
您可以验证是否正在运行任何事件:
SELECT *
FROM performance_schema.threads
WHERE NAME LIKE '%event_worker%'
AND TYPE='FOREGROUND'
其他值得关注的表格:
SELECT * FROM information_schema.processlist