2

I have a bunch of mysql statements (that work on one MyIsam table only) in my PHP script and I don't want to execute these statements concurrently at any time, regardless of how many connections are being used.

For example, two different clients execute the php script on my server and the script opens one mysql connection per each request. I want first to execute the entire bunch of statements in the 1st request and only when this is completed, to execute the bunch of statements in the 2nd request.

I tried:

using "START TRANSACTION" before the bunch of statements => the table is MyIsam and must stay so, so this has no effect.

using "LOCK TABLE t WRITE" before the bunch of statements => locks are not maintained across connections so this doesn't work.

Thanks for help.

5
  • Are you sure that LOCK TABLE does not work? It has to be maintained across connections otherwise it would be totally meaningless. If one connection locks the table for writes, others cannot write to it and will wait - but it won't forbid selects.
    – jkavalik
    Commented Sep 11, 2015 at 13:17
  • I provided a test example showing that it doesnt work: stackoverflow.com/questions/32480842/global-table-lock-mysql. Am I doing something wrong? Commented Sep 11, 2015 at 13:56
  • Will comment on it here - you are probably not checking errors you get from mysql - it would show you syntax error - it is LOCK TABLES not TABLE - dev.mysql.com/doc/refman/5.5/en/lock-tables.html I did not notice it too first time..
    – jkavalik
    Commented Sep 11, 2015 at 18:48
  • 1
    Both LOCK TABLE and LOCK TABLES is allowed syntax (the official manual is incomplete). However, thanks for the hint about errors - indeed I was getting Access denied error while trying to lock the table because I did not configure the mysql user privileges correctly. So, LOCK TABLE approach indeed works. Commented Sep 12, 2015 at 5:04
  • Oh, I see it now used in the examples on that man page too.. Thats why it did not ring the bell first time :)
    – jkavalik
    Commented Sep 12, 2015 at 5:12

1 Answer 1

0

I'm using GET_LOCK and RELEASE_LOCK in this situation.

GET_LOCK() 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 within one session, GET_LOCK() blocks any request by another session for a lock with the same name. This enables clients that agree on a given lock name to use the name to perform cooperative advisory locking. But be aware that it also enables a client that is not among the set of cooperating clients to lock a name, either inadvertently or deliberately, and thus prevent any of the cooperating clients from locking that name. One way to reduce the likelihood of this is to use lock names that are database-specific or application-specific. For example, use lock names of the form db_name.str or app_name.str.

If multiple clients are waiting for a lock, the order in which they will acquire it is undefined. Applications should not assume that clients will acquire the lock in the same order that they issued the lock requests.

Before running a bunch of statements, run:

SELECT GET_LOCK('my unique lock name', 10);

If it returns 1 (success) go on with your bunch of statements and in the end

SELECT RELEASE_LOCK('my unique lock name');

Add some handling of the timeout case, such as retry few times.

It doesn't matter whether your statements work with one table or many tables, whether they are MyIsam, or not. These application-specific locks are server-wide.

3
  • Thanks, this seems to work. LOCK TABLE approach, which I mentioned above does not work, in fact does work, but it turned out the mysql user executing the lock statement did not have the LOCK TABLES privilege. Commented Sep 12, 2015 at 5:03
  • Another benefit of GET_LOCK is that it allows to specify timeout. Commented Sep 12, 2015 at 7:40
  • Caution... If there is a network glitch causing the connection to break, the GET_LOCK will be released.
    – Rick James
    Commented Sep 12, 2015 at 23:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.