{"id":2778,"date":"2017-08-04T12:57:03","date_gmt":"2017-08-04T11:57:03","guid":{"rendered":"http:\/\/www.nivas.hr\/blog\/?p=2778"},"modified":"2017-08-18T15:50:20","modified_gmt":"2017-08-18T14:50:20","slug":"mysql-get_lock-problem-debug-help-mysql-performance_schema","status":"publish","type":"post","link":"https:\/\/www.nivas.hr\/blog\/2017\/08\/04\/mysql-get_lock-problem-debug-help-mysql-performance_schema\/","title":{"rendered":"Mysql GET_LOCK() \u201cproblem\u201d \u2026 and how to debug it with help of mysql  performance_schema"},"content":{"rendered":"<p>After I recently switched back to Linux with php7 and mysql 5.7 I run into \u201cbug\u201d with MySQL GET_LOCK().<br \/>\nI executed php script which uses GET_LOCK(). Scripts were executed parallel (1-2s one after another) from two tabs of the same browser.<br \/>\nAccording to the output, locking was not working!!!<\/p>\n<p><a href=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/programming-knock-knock.jpg\"><img loading=\"lazy\" class=\"aligncenter size-medium wp-image-2797\" src=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/programming-knock-knock-450x450.jpg\" alt=\"\" width=\"450\" height=\"450\" srcset=\"https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/programming-knock-knock-450x450.jpg 450w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/programming-knock-knock-150x150.jpg 150w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/programming-knock-knock-480x480.jpg 480w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/programming-knock-knock.jpg 500w\" sizes=\"(max-width: 450px) 100vw, 450px\" \/><\/a><\/p>\n<p>My first thought was that improvements which were introduced in MySQL 5.7. regarding GET_LOCK() broke something.<\/p>\n<p>Test script:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\r\n$host = 'DB_HOST';\r\n$db   = 'DB_NAME';\r\n$user = 'DB_USER';\r\n$pass = 'DB_PASSWD';\r\n$charset = 'utf8mb4';\r\n\r\n$dsn = &quot;mysql:host=$host;dbname=$db;charset=$charset&quot;;\r\n$opt = [\r\n    PDO::ATTR_ERRMODE            =&gt; PDO::ERRMODE_EXCEPTION,\r\n    PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC,\r\n    PDO::ATTR_EMULATE_PREPARES   =&gt; false,\r\n\tPDO::ATTR_PERSISTENT =&gt; false\r\n];\r\n$pdo = new PDO($dsn, $user, $pass, $opt);\r\n\r\necho &quot;&lt;pre&gt;&quot;;\r\necho &quot;pid=(&quot;.getmypid().&quot;)\\n&quot;;\r\n\r\n$stmt = $pdo-&gt;query('SELECT GET_LOCK(&quot;foobar&quot;, 15)');\r\n$row = $stmt-&gt;fetch();\r\n\r\nvar_dump($row);\r\necho &quot;\\n&quot;;\r\n\r\necho &quot;Sleep for 50s\\n&quot;;\r\nsleep(50);\r\n\r\necho &quot;&lt;\/pre&gt;&quot;;\r\n?&gt;\r\n<\/pre>\n<p>Lock timeout is 15s and script executes (and hold lock) for 50s so I could have time to start both scripts in parallel and monitor MySQL performance_schema.<\/p>\n<p>Result from the first tab:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\npid=(14769)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(1)\r\n}\r\n\r\nSleep for 50s\r\n<\/pre>\n<p>Result from the second tab:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\npid=(14769)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(1)\r\n}\r\n\r\nSleep for 50s\r\n<\/pre>\n<p>Output is not as expected. GET_LOCK() from the second tab should return 0, not 1.<\/p>\n<p>I executed the script again, but from the command line, again in parallel. Second one was executed 1-2s after the first one.<\/p>\n<p>Result from the first (cmd line):<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n$ php -q locktest_1.php \r\n\r\n&lt;pre&gt;pid=(16328)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(1)\r\n}\r\n\r\nSleep for 50s\r\n<\/pre>\n<p>Result from the second (cmd line):<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n$ php -q locktest_1.php \r\n\r\n&lt;pre&gt;pid=(16382)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(0)\r\n}\r\n\r\nSleep for 50s\r\n<\/pre>\n<p>And everything was working as expected. First script obtained the lock, and second didn&#8217;t.<\/p>\n<p>With helpful comments from StackOverflow community I continued with my investigation.<\/p>\n<h2>Put the performance_schema to good use<\/h2>\n<p>In order to see what is happening with my locks it is necessary to monitor performance_schema.threads and performance_schema.metadata_locks closely. To learn more about it check the <a href=\"https:\/\/dev.mysql.com\/doc\/refman\/5.5\/en\/performance-schema.html\" target=\"_blank\">MySQL documentation<\/a>.<\/p>\n<p>I added <a href=\"https:\/\/dev.mysql.com\/doc\/refman\/5.7\/en\/information-functions.html#function_connection-id\" target=\"_blank\">connection_id()<\/a> in php test script in order to match running php script with entries in the performance_schema.threads and performance_schema.metadata_locks tables.<\/p>\n<h2>Second round of tests<\/h2>\n<p>Now, armed with all this data, second round of test can begin.<\/p>\n<p>After running the test scripts I quickly executed these sql queries:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect * from performance_schema.threads;\r\n<\/pre>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nselect * from performance_schema.metadata_locks;\r\n<\/pre>\n<p>You will see active threads and locks and their status (GRANTED, PENDING).<\/p>\n<p>First one returned:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\npid=(14773)\r\nCONNECTION_ID()=(71)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(1)\r\n}\r\nSleep for 50s\r\n<\/pre>\n<p>Second one returned:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\npid=(14773)\r\nCONNECTION_ID()=(72)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(1)\r\n}\r\nSleep for 50s\r\n<\/pre>\n<p>Also in performance_schema.threads there was at any point in time only one entry related to the test script.<br \/>\nFirst it showed:<\/p>\n<p><a href=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/01_blog_post_processlist_id_71_Selection_042.jpg\"><img loading=\"lazy\" class=\"aligncenter size-medium wp-image-2794\" src=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/01_blog_post_processlist_id_71_Selection_042-450x51.jpg\" alt=\"\" width=\"450\" height=\"51\" srcset=\"https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/01_blog_post_processlist_id_71_Selection_042-450x51.jpg 450w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/01_blog_post_processlist_id_71_Selection_042-768x88.jpg 768w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/01_blog_post_processlist_id_71_Selection_042-1024x117.jpg 1024w\" sizes=\"(max-width: 450px) 100vw, 450px\" \/><\/a><\/p>\n<p>Please note row with PROCESSLIST_ID = 71 (matching the output from the first script)<\/p>\n<p>I kept refreshing performance_schema.threads and noticed that one thread related to the test script was replaced with another one. They were not running in parallel like they do when I start test script from cmd line.<\/p>\n<p><a href=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_proccesslist_id_72_Selection_043.jpg\"><img loading=\"lazy\" class=\"aligncenter size-medium wp-image-2793\" src=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_proccesslist_id_72_Selection_043-450x49.jpg\" alt=\"\" width=\"450\" height=\"49\" srcset=\"https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_proccesslist_id_72_Selection_043-450x49.jpg 450w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_proccesslist_id_72_Selection_043-768x83.jpg 768w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_proccesslist_id_72_Selection_043-1024x111.jpg 1024w\" sizes=\"(max-width: 450px) 100vw, 450px\" \/><\/a><\/p>\n<p>Please note row with PROCESSLIST_ID = 72 (matching the output from the second script)<br \/>\nAlso performance_schema.metadata_locks showed only one lock at any point in time (not one GRANTED and one PENDING):<\/p>\n<p><a href=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_thread_96.jpg\"><img loading=\"lazy\" class=\"aligncenter size-medium wp-image-2792\" src=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_thread_96-450x46.jpg\" alt=\"\" width=\"450\" height=\"46\" srcset=\"https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_thread_96-450x46.jpg 450w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_thread_96-768x79.jpg 768w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_thread_96-1024x106.jpg 1024w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/02_blog_post_thread_96.jpg 1501w\" sizes=\"(max-width: 450px) 100vw, 450px\" \/><\/a><\/p>\n<p>For example, when script was executed in parallel from cmd line performance_schema.metadata_locks showed:<\/p>\n<p><a href=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/Selection_044.jpg\"><img loading=\"lazy\" class=\"aligncenter size-medium wp-image-2795\" src=\"http:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/Selection_044-450x48.jpg\" alt=\"\" width=\"450\" height=\"48\" srcset=\"https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/Selection_044-450x48.jpg 450w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/Selection_044-768x82.jpg 768w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/Selection_044-1024x110.jpg 1024w, https:\/\/www.nivas.hr\/blog\/wp-content\/uploads\/2017\/08\/Selection_044.jpg 1531w\" sizes=\"(max-width: 450px) 100vw, 450px\" \/><\/a><\/p>\n<p>For now, it seems that locking is in fact working correctly, but the scripts executed from two tabs of the same browser are not being executed in parallel.<\/p>\n<h2>Third round of tests<\/h2>\n<p>I upgraded the test script to show start timestamp and end timestamp. This also proved that although I started the scripts with 1-2s delay, that they in fact were not running at the same time.<\/p>\n<p>Final test script:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n&lt;?php\r\n\r\n$host = 'DB_HOST';\r\n$db   = 'DB_NAME';\r\n$user = 'DB_USER';\r\n$pass = 'DB_PASSWD';\r\n$charset = 'utf8mb4';\r\n\r\n$dsn = &quot;mysql:host=$host;dbname=$db;charset=$charset&quot;;\r\n$opt = [\r\n    PDO::ATTR_ERRMODE            =&gt; PDO::ERRMODE_EXCEPTION,\r\n    PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC,\r\n    PDO::ATTR_EMULATE_PREPARES   =&gt; false,\r\n\tPDO::ATTR_PERSISTENT =&gt; false\r\n];\r\n$pdo = new PDO($dsn, $user, $pass, $opt);\r\n\r\necho &quot;&lt;pre&gt;&quot;;\r\n\r\necho &quot;start timestamp=(&quot;.date(&quot;c&quot;).&quot;)\\n&quot;;\r\n\r\necho &quot;pid=(&quot;.getmypid().&quot;)\\n&quot;;\r\n\r\n$stmt = $pdo-&gt;query('SELECT CONNECTION_ID() as connid');\r\n$row = $stmt-&gt;fetch();\r\n\r\necho &quot;CONNECTION_ID()=(&quot;.$row['connid'].&quot;)\\n&quot;;\r\n\r\n$stmt = $pdo-&gt;query('SELECT GET_LOCK(&quot;foobar&quot;, 15)');\r\n$row = $stmt-&gt;fetch();\r\n\r\nvar_dump($row);\r\necho &quot;\\n&quot;;\r\n\r\necho &quot;Sleep for 50s\\n&quot;;\r\nsleep(50);\r\n\r\necho &quot;end timestamp=(&quot;.date(&quot;c&quot;).&quot;)\\n&quot;;\r\necho &quot;&lt;\/pre&gt;&quot;;\r\n?&gt;\r\n<\/pre>\n<p>First one returned:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nstart timestamp=(2017-08-03T14:30:48+00:00)\r\npid=(14768)\r\nCONNECTION_ID()=(73)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(1)\r\n}\r\nSleep for 50s\r\nend timestamp=(2017-08-03T14:31:38+00:00)\r\n<\/pre>\n<p>Second one returned:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nstart timestamp=(2017-08-03T14:31:38+00:00)\r\npid=(14768)\r\nCONNECTION_ID()=(74)\r\narray(1) {\r\n  [&quot;GET_LOCK(&quot;foobar&quot;, 15)&quot;]=&gt;\r\n  int(1)\r\n}\r\nSleep for 50s\r\nend timestamp=(2017-08-03T14:32:28+00:00)\r\n<\/pre>\n<p>Please note the end timestamp of the first and start timestamp of the second script.<\/p>\n<h2>Conclusion<\/h2>\n<p>Execution of the scripts was serialized. They definitely didn&#8217;t run in parallel and that was the reason why both succeeded to acquire the lock.<\/p>\n<p>GET_LOCK() in MySQL 5.7 is still working as it should (plus the improvements). But even more important, I realized what a powerful tool Performance Schema is in debugging what at first appeared to be really weird bug.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>After I recently switched back to Linux with php7 and mysql 5.7 I run into \u201cbug\u201d with MySQL GET_LOCK(). I executed php script which uses GET_LOCK(). Scripts were executed parallel (1-2s one after another) from two tabs of the same browser. According to the output, locking was not working!!! My first thought was that improvements&#8230;<\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/posts\/2778"}],"collection":[{"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/comments?post=2778"}],"version-history":[{"count":17,"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/posts\/2778\/revisions"}],"predecessor-version":[{"id":2808,"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/posts\/2778\/revisions\/2808"}],"wp:attachment":[{"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/media?parent=2778"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/categories?post=2778"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nivas.hr\/blog\/wp-json\/wp\/v2\/tags?post=2778"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}