Application semaphores using MySQL
Many tasks require some application part to run in one instance per time, such as mail delivery cron job. And each time developers should invent some mechanism to determine if another copy is running. Usually no of these mechanisms are 100% reliable.
The solution is already found by MySQL development team. It is "named locks".
Application can try to acquire a named lock on its start and check if another copy is running.
How can it be implemented:
$res = mysql_query("SELECT GET_LOCK('lockname', 2)");
$result = mysql_fetch_array($res);
if (!intval($result[0])) {
echo "Cannot run until previous instance finish!";
exit;
}
// Do anything we need
mysql_query("SELECT RELEASE_LOCK('lockname')");
What we get using this mechanism:
- GET_LOCK will fail if a lock with specified name already set and script can stop;
- Script can work as long time as it needs;
- RELEASE_LOCK will free acquired lock and script will run successfully next time;
- If the script will fail with fatal error, time restriction or somehow else, MySQL will free its lock automatically on connection close;
- No additional files, table records, no stupid checks. Everything is done in 2 queries;
- We can be 100% sure another copy is running now, no lost locks;
Note: All the above is true if you use only one lock per script (and probably without persistent connection) because callng GET_LOCK second time during the same session will release previous lock. This feature is very usefull for cronjobs.
To read more about these functions - visit MySQL Manual
August 20th, 2009 - 05:04
# GET_LOCK will fail if a lock with specified name already set and script can stop; -no it will not. what makes you to be 100% sure…
from http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock:
*If you have a lock obtained with GET_LOCK(), it is released when you execute RELEASE_LOCK(), !!!!execute a new GET_LOCK()!!!!, or your connection terminates (either normally or abnormally).
August 20th, 2009 - 10:24
Agree, but the next paragraph on the same page tells:
>>>
This function can be used to implement application locks or to simulate record locks. Names are locked on a server-wide basis. If a name has been locked by one client, GET_LOCK() blocks any request by another client for a lock with the same name. This allows clients that agree on a given lock name to use the name to perform cooperative advisory locking.
<<<
I have successfully used it in cronjobs to prevent multiple job instances running at the same time.
I added a notice. Thank you for warning.
March 13th, 2010 - 12:55
You have tested it and writing form your personal experience or you find some information online?
March 28th, 2010 - 17:16
Yes, I wrote it from my personal experience. I usually use it in cronjobs to guarantee that I run only single script instance.