欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Lock wait timeout exceeded; try restarting transaction: DELETE FROM {apache solr index entities file} 有大用 有大大用


获取“超出锁定等待超时;尝试重新启动事务”,即使我没有使用事务



                   

                   

407                    

           

我正在运行以下 MySQLUPDATE语句:                

mysql> update customer set account_import_id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
               

我没有使用事务,为什么会出现此错误?我什至尝试重新启动我的 MySQL 服务器,但没有帮助。                

该表有 406,733 行。                

                               
   

23个答案                

   
471                    
               

如何强制解锁 MySQL 中锁定的表:                    

像这样破坏锁可能会导致数据库中的原子性无法对导致锁的 sql 语句强制执行。                    

这是 hackish,正确的解决方案是修复导致锁定的应用程序。然而,当美元岌岌可危时,迅速的一脚会让事情再次发生变化。                    

1)进入MySQL                    

mysql -u your_user -p
                   

2)让我们看看锁定表的列表                    

mysql> show open tables where in_use>0;
                   

3)让我们看看当前进程的列表,其中之一正在锁定您的表                    

mysql> show processlist;
                   

4)杀死其中一个进程                    

mysql> kill <put_process_id_here>;
               
                                   
  • 36                                
    这是危险和骇人听闻的。正确的解决方案是修复您的应用程序。 
    – Zenexer                                    
     2015 年 7 月 9 日 13:44                                
  • 118                                
    废话,这可以让您撤消混乱,然后修复应用程序。如果我能为这个我现在必须解决的问题给这个人 100 票赞成票,我会的。 
    – 蜥蜴                                    
     2016 年 5 月 26 日 21:44                                
  • 9                                
    我同意 Lizardx。在我没有权限调用 SHOW ENGINE INNODB STATUS 的情况下,这是一个非常有用的解决方案 
    – 特拉维斯施尼伯格                                    
     2016 年 11 月 1 日 16:55                                
  • 12                                
    以这种方式终止长时间运行的查询有多危险客户端调用只会出错。 
    – 至强越野                                    
     2018 年 9 月 13 日 21:52                                
  • 14                                
    @EricLeschinski 我明白你的意思,但我不得不问为什么你会在生命关键系统上使用像MySQL这样草率的数据库 
    – 至强越野                                    
     2018 年 11 月 19 日 18:09                                
   
268                    
               

您正在使用交易;autocommit 不会禁用事务,它只是让它们在语句末尾自动提交。                    

可能发生的情况是,其他某个线程在某个记录上持有记录锁(您正在更新表中的每条记录!)时间过长,并且您的线程正在超时。或者可能在单个事务期间对同一行运行多个 (2+) UPDATE 查询。                    

您可以通过发出一个消息来查看事件的更多详细信息                    

SHOW ENGINE INNODB STATUS
                   

事件之后(在 SQL 编辑器中)。理想情况下在安静的测试机上执行此操作。                    

                                   
  • 2个                                
    有没有办法将输出保存到文件中?我试过 SHOW ENGINE INNODB STATUS\G > innodb_stat.txt 但不起作用。 
    – 燕塔克                                    
     2015 年 2 月 18 日 20:32                                
  • 19                                
    从命令行:mysql [insert credentials] -e "SHOW ENGINE INNODB STATUS\G" > innodb_stat.txt 
    – 尊贵特工                                    
     2015 年 3 月 24 日 18:37                                 
  • 如果很多mysql线程(或进程)很忙,例如一些查询需要很长时间,所以你必须等待一些process空闲。如果是这样,您可能会收到此错误。我对吗? 
    – 朱国伟                                    
     2016 年 8 月 4 日 9:36                                
  • 12                                
    在单个事务期间对同一行运行多个 (2+) UPDATE 查询也会导致此错误。 
    – 奥克诺珀                                    
     2018 年 12 月 3 日 23:02                                
  • 1个                                
    对于那些使用 Python MySQL Connector 的用户,请使用connection.commit()提交INSERT或者UPDATE您刚刚通过。 
    – 空气能                                    
     2019 年 9 月 12 日 7:00                                
   
143                    
               
mysql> set innodb_lock_wait_timeout=100;

Query OK, 0 rows affected (0.02 sec)

mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 100   |
+--------------------------+-------+
                   

现在再次触发锁定。SHOW ENGINE INNODB STATUS\G您有 100 秒的时间向数据库发出 a并查看哪个其他事务正在锁定您的事务。                    

                                   
  • 9                                
    这个答案没有解释为什么提问者会得到他们的错误。除了给出答案之外,您能否详细说明原因? 
    – 雪橇                                    
     2012 年 11 月 15 日 21:00                                
  • 13                                
    +1 虽然这并没有直接回答问题,但对我来说这是解决此问题的一个很好的参考。 
    – 约瑟夫·哈鲁什·嘉杜里                                    
     2016 年 2 月 17 日 12:56                                
  • 1个                                
    @ArtB dev.mysql.com/doc/refman/8.0/en/…本质上,OP 收到错误是因为在表上调用了锁并且结束事务之前经过的时间超过了lock_wait_timeout 
    – 威尔 B。                                    
     2016 年 5 月 2 日 3:42                                 
   
94                    
               

看一下您的数据库是否经过微调,尤其是事务隔离。增加变量不是一个好主意innodb_lock_wait_timeout                    

检查 MySQL 中的数据库事务隔离级别:                    

mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation, @@session.tx_isolation;
+-----------------------+-----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation  | @@session.tx_isolation |
+-----------------------+-----------------+------------------------+
| REPEATABLE-READ       | REPEATABLE-READ | REPEATABLE-READ        |
+-----------------------+-----------------+------------------------+
1 row in set (0.00 sec)
                   

您可以获得更改隔离级别的改进。使用类 OracleREAD COMMITTED而不是REPEATABLE READREPEATABLE READ是 InnoDB 的默认值。                    

mysql> SET tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)
                   

另外,尽量只在必要时使用SELECT FOR UPDATE                    

                                   
  • 1个                                
    这是锁定问题的绝佳解决方案。 
    – 芬芳的                                    
     2014 年 9 月 24 日 21:09                                
  • 4个                                
    对我来说很棒,my.cnf 版本是 [mysqld] transaction-isolation = READ-COMMITTED 
    – 贝努瓦·高捷                                    
     2016 年 9 月 23 日 21:10                                 
  • 13                                
    请注意:MySQL 8 已将tx_isolation变量重命名为transaction_isolation. 
    – xonya                                    
     2020 年 5 月 21 日 15:44                                
  • 2个                                
    但是,当您从读取隔离更改为读取已提交时,必须小心知道您将进入什么状态。您最终可能会得到想要避免的脏数据。维基百科隔离 
    – 拥抱                                    
     2020 年 5 月 25 日 9:52                                
  • 这对我有用。使用 python,SQL Alchemy 给了我一个警告,我总是忽略它,但在阅读它时,它可能是相关的:Warning: '@@tx_isolation' is deprecated and will be removed in a future release. 请使用 '@@transaction_isolation' 而不是 cursor.execute('SELECT @@tx_isolation') - 隔离设置为 READ-REPEATABLE,但在将其设置为 READ-COMMITTED 后,锁定问题已解决。我运行的进程使用大约 8 个线程写入数据库。 
    – 咖啡与代码                                    
     2020 年 7 月 4 日 13:51                                 
   
46                    
               

某些东西阻止了查询的执行。很可能是另一个查询更新、插入或从您的查询中的一个表中删除。你必须找出那是什么:                    

SHOW PROCESSLIST;
                   

找到阻塞进程后,找到它id并运行:                    

KILL {id};
                   

重新运行您的初始查询。                    

                                   
  • 1个                                
    我不小心杀死了 SHOW PROCESSLIST 列出的所有进程;现在我在 phpmyadmin 中收到 500 错误。500 错误是否与终止这些进程有关?如果是,我该如何重新启动它。 
    – 达什拉斯                                    
     2016 年 11 月 7 日 6:29                                
  • 我可以看到你描述的内容,但是终止进程不起作用。进程的命令被“杀死”,但它仍保留在进程列表中。 
    – 托斯滕                                    
     2019 年 7 月 9 日 13:41                                
   
14                    
               
mysql->SHOW PROCESSLIST;
kill xxxx; 
                   

然后在睡眠中杀死哪个。在我的例子中是 2156。                    

在此处输入图像描述                    

                                   
   
12                    
               

100% 与 MarkR 所说的一致。autocommit 使每个语句成为一个语句事务。                    

SHOW ENGINE INNODB STATUS应该给你一些关于死锁原因的线索。仔细查看您的慢速查询日志,看看还有什么在查询表,并尝试删除任何正在执行完整表扫描的内容。行级锁定效果很好,但当您尝试锁定所有行时效果不佳!                    

                                   
   
6个                    
               

尝试更新以下两个参数,因为它们必须具有默认值。                    

innodb_lock_wait_timeout = 50                        

innodb_rollback_on_timeout = ON                        

要检查参数值,您可以使用以下 SQL。                    

显示像“innodb_rollback_on_timeout”这样的全局变量;                        

                                   
   
5个                    
               

您能否更新此表中的任何其他记录,或者此表是否被大量使用?我在想的是,当它试图获取需要更新此记录的锁时,设置的超时已超时。您可以增加时间,这可能会有所帮助。                    

                                   
  • 3个                                
    也许innodb_lock_wait_timeoutmy.cnf 
    – 卡尔·安德鲁                                    
     2011 年 4 月 29 日 19:51                                 
  • 1个                                
    我在my.cnf中设置:<br/>innodb_lock_wait_timeout=120<br/>mysql 5.5默认是50。进行此更改后,我无法在单元测试中看到此问题!这是从proxool切换到tomcat jdbc pool后发生的。可能是因为与 tomcat 池的交易时间更长?! 
    – 冠军                                    
     2012 年 11 月 7 日 9:21                                 
   
4个                    
               

如果您刚刚终止了一个大查询,那么rollback如果您在终止的查询完成回滚之前发出另一个查询,您可能会收到锁定超时错误。那就是发生在我身上的事。解决办法只是稍等一下。                    

细节:                    

我发出了一个 DELETE 查询,从大约 100 万行中删除了大约 900,000 行。                    

我错误地运行了这个(只删除了 10% 的行): DELETE FROM table WHERE MOD(id,10) = 0                    

而不是这个(删除 90% 的行): DELETE FROM table WHERE MOD(id,10) != 0                    

我想删除 90% 的行,而不是 10%。所以我在 MySQL 命令行中终止了该进程,因为我知道它会回滚到目前为止已删除的所有行。                    

然后我立即运行了正确的命令,但lock timeout exceeded很快就报错了。我意识到锁实际上可能是rollback仍在后台发生的已终止查询的锁。所以我等了几秒钟,然后重新运行查询。                    

                                   
  • 当服务器在大型更新期间重新启动时,我遇到了同样的事情。 
    – 用户1125572                                    
     2022 年 10 月 31 日 14:58                                
   
4个                    
               

在我们的案例中,问题与锁本身没有太大关系。                    

问题是我们的应用程序端点之一需要并行打开 2 个连接来处理单个请求。                    

例子:                    

  1. 打开第一个连接

  2. 开始事务 1

  3. 锁定 table1 中的 1 行

  4. 打开第二个连接

  5. 开始事务 2

  6. 锁定 table2 中的 1 行

  7. 提交事务 2

  8. 释放第二个连接

  9. 提交事务 1

  10. 释放第一个连接

我们的应用程序有一个限制为 10 个连接的连接池。                    

不幸的是,在负载下,一旦所有连接都被使用,应用程序就会停止工作,我们开始遇到这个问题。我们有几个请求需要打开第二个连接才能完成,但由于连接池限制而无法完成。因此,这些请求长时间锁定 table1 行,导致以下请求需要锁定同一行以抛出此错误。                    

解决方案:                    

  • 在短期内,我们通过增加连接池限制来修补该问题。

  • 从长远来看,我们删除了所有嵌套连接,以彻底解决问题。

尖端:                    

您可以通过尝试将连接池限制降低到 1 并测试您的应用程序来轻松检查您是否有嵌套连接。                    

                                   
   
2个                    
               

行数不是很大...如果它不是主键,则在 account_import_id 上创建一个索引。                    

CREATE INDEX idx_customer_account_import_id ON customer (account_import_id);
               
                                   
  • 天哪……这救了我。我通过删除索引彻底搞砸了生产数据库,这修复了它。感谢您。 
    – 尼克·戈奇                                    
     2016 年 12 月 21 日 3:55                                
   
1个                    
               

确保数据库表使用 InnoDB 存储引擎和 READ-COMMITTED 事务隔离级别。                    

你可以通过 SELECT @@GLOBAL.tx_isolation, @@tx_isolation; 查看 在 mysql 控制台上。                    

如果它没有被设置为 READ-COMMITTED 那么你必须设置它。在设置它之前确保您在 mysql 中具有 SUPER 权限。                    

您可以从http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html获得帮助。                    

通过设置这个我认为你的问题会得到解决。                    


您可能还想检查您是否试图同时在两个进程中更新它。用户 (@tala) 在这种情况下遇到过类似的错误消息,也许仔细检查一下......                    

                                   
   
1个                    
               

我来自谷歌,我只是想添加适合我的解决方案。我的问题是我试图删除一个巨大的表的记录,该表有很多 FK 级联,所以我得到了与 OP 相同的错误。                    

我禁用了autocommit然后它只是COMMIT在 SQL 语句的末尾添加。据我了解,这会一点一点地释放缓冲区,而不是在命令结束时等待。                    

为了与 OP 的示例保持一致,这应该有效:                    

mysql> set autocommit=0;                    

mysql> update customer set account_import_id = 1; commit;                    

autocommit如果您想像以前一样保留 MySQL 配置,请不要忘记重新激活。                    

mysql> set autocommit=1;                    

                                   
   
0                    
               

晚会(像往常一样)但是我的问题是我写了一些糟糕的 SQL(作为新手)并且几个进程锁定了记录 < - 不确定适当的措辞。我最终不得不:SHOW PROCESSLIST然后使用杀死IDKILL <id>                    

                                   
   
0                    
               

我在使用php语言construct exit的时候就发生过这种事情;在交易中间。然后这个事务“挂起”,你需要杀死 mysql 进程(上面用 processlist 描述;)                    

                                   
   
0                    
               

在我的例子中,我运行了一个异常查询来修复数据。 如果您在查询中锁定表,那么您将不必处理锁定超时:                    

LOCK TABLES `customer` WRITE;
update customer set account_import_id = 1;
UNLOCK TABLES;
                   

这对于正常使用来说可能不是一个好主意。                    

有关详细信息,请参阅: MySQL 8.0 参考手册                    

                                   
   
0                    
               

我遇到了这个有 2 个 Doctrine DBAL 连接,其中一个是非事务性的(对于重要日志),它们旨在并行运行而不相互依赖。                    

CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery()
)
                   

在非常测试之后,我的集成测试被包装到事务中以进行数据回滚。                    

beginTransaction()
CodeExecution(
    TransactionConnectionQuery()
    TransactionlessConnectionQuery() // CONFLICT
)
rollBack()
                   

我的解决方案是在这些测试中禁用包装事务并以另一种方式重置数据库数据。                    

                                   
   
0                    
               

我们昨天遇到了这个问题,在仔细研究了这里几乎所有建议的解决方案以及来自其他答案/论坛的其他几个解决方案之后,我们在意识到实际问题后最终解决了它。                    

由于一些糟糕的计划,我们的数据库存储在一个已安装的卷上,该卷也接收我们的定期自动备份。该卷已达到最大容量。                    

一旦我们清理了一些空间并重新启动,这个错误就解决了。                    

请注意,我们也确实手动终止了几个进程:kill <process_id>;所以这可能仍然是必要的。                    

总的来说,我们的收获是令人难以置信的沮丧,因为我们的日志或警告都没有直接提到磁盘空间不足,但这似乎是根本原因。                    

                                   
   
0                    
               

我在使用python访问mysql数据库时也有类似的错误。
python 程序使用了 while 和 for 循环。
在适当的行关闭光标和链接解决了问题
https://github.com/nishishailesh/sensa_host_com/blob/master/sensa_write.py 参见第 230 行
似乎在不关闭先前链接的情况下询问重复链接会产生此错误                    

                                   
   
0                    
               

我在做一些测试时遇到了类似的问题。                    

原因——在我的例子中,事务不是从我的 spring boot 应用程序提交的,因为我在执行期间杀死了 @transactional 函数(当函数正在更新某些行时)。由于哪个事务从未提交给数据库(MySQL)。                    

结果- 无法从任何地方更新这些行。但能够更新表的其他行。                    

mysql> update some_table set some_value = "Hello World" where id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
                   

解决方案- 杀死所有使用的 MySQL 进程                    

  • sudo killall -9 mysqld

在此处输入图像描述                    

  • sudo killall -9 mysqld_safe(发生错误时重新启动服务器并将运行时信息记录到错误日志中。在我的情况下不需要)

                                   
   
0                    
               

我的场景在更新或删除后无法提交。                    

显示进程列表                    

显示了一长串睡眠连接。                    

                                   
   
-4                    
               

有同样的错误,即使我只用一个条目更新一个表,但在重新启动 mysql 后,它就解决了。                    

                                   

不是您要找的答案?浏览其他标记的问题            或者问你自己的问题        


来自  https://stackoverflow.com/questions/5836623/getting-lock-wait-timeout-exceeded-try-restarting-transaction-even-though-im  

https://stackoverflow.com/questions/5836623/getting-lock-wait-timeout-exceeded-try-restarting-transaction-even-though-im


普通分类: