5

I am attempting to lock some tables while running some code and unlocking the tables when I am done.

Process:

  1. Run Lock Tables MySQL Query.
  2. Run some PHP Code.
  3. Run Unlock Tables MySQL Query.

While running this process, 9 times out of 10 everything runs perfectly. Sometimes, when I run my query no response comes back from MySQL and PHP just waits for a response. Since no response happens, I never get to steps 2 or 3 and the table stays locked indefinitely. I am running the exact same Lock Tables Query in every single attempt.

I am locking Numerous tables. Below is a similar example to my actual table query. I am using the same table multiple times with different aliases based on the queries I am attempting to prevent from accessing the tables.

$sql = "LOCK TABLES table1 as t1 WRITE
                    , table2 as t2 WRITE
                    , table3 WRITE
                    , table2 WRITE
                    , table4 WRITE
                    , table1 WRITE
                    , table5 WRITE
                    , table5 as t5 WRITE
                    , table6 as t6 WRITE
                    , table7 as t7 WRITE
                    , table7 WRITE
                    , table8 as t8 WRITE
                    , table9 t9 WRITE
                    , table10 t10 WRITE
                    , table11 t11 WRITE
                    , table12 WRITE;";

$this->mysqli = new mysqli(
    $this->credentials->server
    , $this->credentials->user
    , $this->credentials->password
    , $this->credentials->database
);

try{
    error_log('before first attempt lock tables '.$sql);
    $this->mysqli->query($sql);
    error_log('after first attempt lock tables');
} catch (Exception $e){
    error_log('Error locking tables: '.$e->getMessage());
}

error_log('After try catch.');
if($this->mysqli->error){
    error_log('lock table error: '.$this->mysqli->error);
}

When the process fails, I see "before first attempt lock tables" in my PHP Error log. I do not see any of the other error_log() calls. After some checking, I determined it is because PHP has not received a response from MySQL.

I never get into the Catch Exception, since MySQL is not returning an error. MySQL is not returning anything unless I manually kill the MySQL Lock Tables Process.

If I don't kill the process, the PHP code never stops waiting for a response from mysql.

Daryl
  • 772
  • 8
  • 21
  • Some other clients probably have the tables locked, so it's never able to grab all the locks it needs. – Barmar Nov 04 '16 at 23:03
  • @Barmar thank you for your input. I considered this and verified that I am the only user trying to lock the table. So I am still not sure what would cause the issue. – Daryl Nov 04 '16 at 23:08
  • Do you see the `LOCK TABLES` query in `show processlist;`? What does it say it's doing? – Barmar Nov 04 '16 at 23:14
  • What is your code doing, that you need to lock so many tables manually? – michaJlS Nov 04 '16 at 23:17
  • @Barmar The `show processlist;` has `Waiting for table metadata lock | LOCK TABLES ...` in it. – Daryl Nov 04 '16 at 23:41
  • See https://dev.mysql.com/doc/refman/5.5/en/metadata-locking.html – Barmar Nov 04 '16 at 23:44
  • Also http://stackoverflow.com/questions/13148630/how-do-i-find-which-transaction-is-causing-a-waiting-for-table-metadata-lock-s – Barmar Nov 04 '16 at 23:45
  • And http://stackoverflow.com/questions/19801139/mysql-permanently-getting-waiting-for-table-metadata-lock – Barmar Nov 04 '16 at 23:45
  • @Barmar it took some time, but I finally found the cause: I have two servers writing to the Database. The MySQL autocommit feature on the database is enabled. The second server was doing an update on one of the tables that the first server was doing a "LOCK TABLES" command on. The second server was apparently creating a "metadata lock" during its update, so if the first server tried to do the lock table at the same time it then failed to ever complete. It was my understanding that both connections are allowed to do locks without one failing. So I am not sure why this is happening. – Daryl Nov 08 '16 at 23:33
  • @Barmar As a work around to the issue, I moved all of the Updates from the Second Server to be done via an API call to the first server. This resolved the problem. However, I do not understand why both servers cannot write to the database and have the "LOCK TABLES" command on the first server work with the Transactional Metadata Locks done by the second server. I would think that the "LOCK TABLES" command on the first server, would wait for the Meta Datalocks to be completed and then run. – Daryl Nov 08 '16 at 23:51
  • I don't understand it, either. My understanding is that metadata locks are only grabbed when you're modifying the schema (e.g. `ALTER TABLE`), not by ordinary `LOCK TABLE` commands. And in either case it shouldn't cause the other client to hang forever, the metadata lock should eventually be released and the other client will be allowed in. You might want to ask a question on dba.SE, that's where you'll find the experts on database configuration. – Barmar Nov 09 '16 at 17:01
  • @Barmar Thanks for the suggestion. I posted the question to the DBA Stack Exchange. Hopefully I'll get a response! – Daryl Nov 10 '16 at 21:32

0 Answers0