php - Prevent parallel execution using a table lock (MySQL) -


i have mysql table called cronjobs holds entires every cronjob needed (e.g. delete old emails, update profile age, , on). every cronjob there defined code block gets executed if cronjob due (i got different intervals different cronjobs).

for execution of due cronjobs, got php script executed unix crontab every minute (calls execute_cronjobs_due.sh calls "php -f /path/to/file/execute_cronjobs_due.php").

when executing execute_cronjobs_due.php cronjobs marked going executed, call of execute_cronjobs_due.php wouldn't cause parallel execution of same cronjob getting executed.

now problem: execution takes more 60 seconds crontab program not call execute_cronjobs_due.sh after these 60 seconds. happens execute_cronjobs_due.sh called right after execution of execution of previous crontab. , if execution takes more 120 seconds, next 2 executions initialize simultaneously.

timeline:

2015-06-15 10:00:00: execution execute_cronjobs_due.sh (takes 140 seconds)

2015-06-15 10:02:20: 2 simultaneous executions of execute_cronjobs_due.sh

since executed simultaneous, there no use of marking cronjob being executed since selects (which should exclude marked once) executed @ exact same time. update occurs right after both selected due cronjobs.

how can solve problem, there no simultaneous executions of cronjobs? can use mysql table locks?

thank in advance,

frederic

yes use mysql table locks, may overkill situation. anyway in generic way

  1. make sure have autocommit off
  2. lock tables cronjobs;
  3. do stuff
  4. unlock tables

for exact syntax , details read docs obviusly https://dev.mysql.com/doc/refman/5.0/en/lock-tables.html , never used table level locking maybe there catches involved not aware of.

what do, if use innodb table engine go optimistic locking:

  1. start transaction first thing in script
  2. get id of script or whatever, might process pid (getmypid()) or combination of host+pid. or generate guid if don't know perfect
  3. do update cronjobs set executed_by = my_id executed_by null , /* whatever condition jobs run */
  4. then select * cronjobs executed_by = my_pid
  5. do stuff on whatever above select returned
  6. update cronjobs set executed_by = null executed_by = my_pid

this should easy do, easier track happens , scale in future (i.e. can have few instances running running in parallel long execute different scripts)

with solution second script not fail (technically), run 0 jobs.

minus have clean jobs claimed script failed mark them finished, have anyway current solution. easiest way add timestamp column track when job claimed last time , expire after i.e. 15 minutes or hour depending on business requirements (short pseudocode: first update set executed_by = my_id, started_at = now() executed_by null or (executed_by not null , started_at < now() - 1 hour))


Comments

Popular posts from this blog

javascript - Google App Script ContentService downloadAsFile not working -

javascript - Function overwritting -

php - Find a regex to take part of Email -