MySQL“LOCK TABLES”超时?

时间:2015-05-06 11:12:29

标签: mysql transactions locking innodb

mysql LOCK TABLES语句的超时是什么时候?

无法在任何地方找到它。

我试图设置变量innodb_lock_wait_timeout ini my.cnf但似乎它与另一个(行级别)锁定而不是表锁定有关。

对LOCK TABLES没有任何影响。

我想为死锁的情况设置一些低超时值,因为如果某些操作会使LOCK表出现错误,它会挂起整个站点!

例如,在您的网站上完成购买时,这是愚蠢的。

5 个答案:

答案 0 :(得分:2)

我的解决方法是创建一个专用的锁表,然后在该表中锁定一行。这具有仅锁定特别想要锁定的进程的优点。应用程序的其他部分可以继续访问表,即使它们在某些时候被更新过程触及。

设置

CREATE TABLE `mutex` (
    EMPTY ENUM('') NOT NULL,
    PRIMARY KEY (EMPTY)
);

用法

set innodb_lock_wait_timeout = 1;
start transaction;
insert into `mutex` values();

[... do the real work here ... or somewhere else ... even a different machine ...]

delete from `mutex`;
commit;

答案 1 :(得分:1)

您为什么使用LOCK TABLES

如果您使用的是MyISAM(有时需要LOCK TABLES),您应该转换为InnoDB。

如果您使用的是InnoDB,则不应使用LOCK TABLES。相反,取决于innodb_lock_wait_timeout(默认是不合理的高50秒)。你应该检查错误。

InnoDB死锁被捕获并立即导致错误。某些非死锁可能会等待innodb_lock_wait_timeout。

修改

由于交易看起来像

BEGIN;
SELECT ...;
compute some stuff
UPDATE ... (using that stuff);
COMMIT;

您需要在FOR UPDATE

的末尾添加SELECT

答案 2 :(得分:0)

我想你的意思是说默认的超时值;它是50 SecondsMySQL Documentation它说

  

innodb_lock_wait_timeout默认值50以秒为单位的超时时间   在放弃之前,InnoDB事务可能会等待行锁定。该   默认值为50秒

答案 3 :(得分:0)

我认为你是在MySQL 5.0.10中引入的table_lock_timout变量之后但随后是removed in 5.5。不幸的是,发行说明没有指定使用的替代方案,我猜测一般的态度是切换到使用InnoDB交易,正如@Rick James在他的回答中所述。

我认为删除变量是无益的。其他人可能会将此视为XY Problem的情况,我们正在尝试通过更改锁定表的超时时间来修复症状(死锁),而实际上我们应该通过切换到事务来解决根本原因。 我认为可能仍然存在表锁比使用事务更适合应用程序的情况,并且可能更容易理解,即使它们表现更差。

使用LOCK TABLES的好处是,您可以在继续之前说明您查询所依赖的表。对于事务,锁会在最后可能的时刻被抓取,如果无法获取和超时,则需要检查此故障并在重新尝试所有内容之前回滚。在锁定表查询上有1秒的超时(最小值)更简单,并且在您成功之前继续重试以获取锁定,然后在解锁表之前继续执行查询。这种逻辑不存在死锁的风险。

我相信开发人员的态度总结为documetation的以下摘录:

  

...避免使用LOCK TABLES语句,因为它没有提供   任何额外的保护,但反而降低了并发性。

答案 4 :(得分:0)

正确答案是lock_wait_timeout系统变量。

来自文档:

  

此变量指定尝试获取的超时(以秒为单位)   元数据锁。允许值范围为1到31536000(1   年)。默认值为31536000。

     

此超时适用于使用元数据锁的所有语句。这些   包括对表,视图,存储过程的DML和DDL操作,   和存储的函数,以及LOCK TABLES,FLUSH TABLES WITH READ   LOCK和HANDLER声明。