简体   繁体   English

innodb_lock_wait_timeout 超时被忽略

[英]innodb_lock_wait_timeout timeout is ignored

I'm trying to do MySQL locks implementation in PHP (I need both shared and exclusive, so I can't use GET LOCK).我正在尝试在 PHP 中实现 MySQL 锁(我需要共享和独占,所以我不能使用 GET LOCK)。

<?php
$conn = new \Pdo('mysql:host=localhost;dbname=locks', 'root', 'root', [\PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$conn->exec('INSERT IGNORE INTO locksPoc (lockName) VALUES ("mylock")');
$conn->exec('set session innodb_lock_wait_timeout = 1');
$this->dump('Lock exists in DB');
$conn->beginTransaction();
$rows = $conn->query('SELECT * FROM locksPoc WHERE lockName="mylock" FOR UPDATE');
$row = $rows->fetchAll();
$this->dump('Got the lock');
sleep(30);
$conn->commit();

When I run it in parallel like this:当我像这样并行运行它时:

$ php db.php &
$ php db.php &

It does not work as expected.它没有按预期工作。 The second one outputs "Lock exists in DB" immediately but then proceeds to wait 30s before the other script is finished.第二个立即输出“Lock exists in DB”,然后在另一个脚本完成之前等待 30 秒。 My expectation was that it will fail after 1s with exception because of the lock timeout.我的期望是由于锁定超时,它会在 1 秒后失败并出现异常。

The answer is revealed if you use SHOW PROCESSLIST:如果您使用 SHOW PROCESSLIST,答案就会揭晓:

mysql> show processlist;
+----+-----------------+-----------+-------+---------+--------+------------------------+----------------------------------------------------------+
| Id | User            | Host      | db    | Command | Time   | State                  | Info                                                     |
+----+-----------------+-----------+-------+---------+--------+------------------------+----------------------------------------------------------+
| 24 | root            | localhost | test2 | Query   |      6 | update                 | INSERT IGNORE INTO locksPoc (lockName) VALUES ("mylock") |

The second invocation of the script is waiting on the INSERT, which is executed by your script before you change the innodb_lock_wait_timeout to 1 second.脚本的第二次调用正在等待 INSERT,在您将innodb_lock_wait_timeout更改为 1 秒之前,该脚本由您的脚本执行。 The default is 50 seconds.默认值为 50 秒。

INSERT IGNORE does not change locking behavior or timeouts. INSERT IGNORE 不会更改锁定行为或超时。 It only makes errors downgrade to warnings.它只会使错误降级为警告。 The timeout is still 50 seconds when you run your INSERT.运行 INSERT 时,超时仍为 50 秒。

I have to observe that it looks like you're trying to implement a feature for named advisory locking that is already built-in to MySQL with the GET_LOCK() function .我必须观察到,您似乎正在尝试使用GET_LOCK() 函数实现已内置于 MySQL 的命名咨询锁定功能。 That function already has a timeout argument, so you don't have to rely on changing the InnoDB row-level locking timeout.该函数已经有一个超时参数,因此您不必依赖更改 InnoDB 行级锁定超时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM