Can I avoid two MySQL events running at the same time?

99封情书 提交于 2019-12-12 02:09:52

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!