有没有办法不在MySQL中锁定?

时间:2010-11-12 16:10:49

标签: mysql deadlock database-deadlocks

我有一个查询,我每天运行一次,从我的数据库中获取某些表并将它们放入一个表中,以便我可以快速导出我需要的任何格式的信息。

我遇到了一个问题然而却给了我以下错误:“SQLSTATE [40001]:序列化失败:1213尝试获取锁定时发现死锁;尝试重新启动事务”

根据我的理解,听起来我的查询是在已经存在锁定时尝试锁定表。但是我承认我对表锁定或它是如何工作一无所知。

我真的只是想读取其他表而不是写入它们,有没有办法可以创建查询而不是请求锁定?

我的查询非常漫长,所以我没有发布它。如果您需要某些部件让我知道,我可以发布它们。

2 个答案:

答案 0 :(得分:2)

如果您处于事务隔离模式REPEATABLE_READ(这是默认设置),则选择不应创建任何锁。这很正常。

但是,如果你正在使用insert ...当然,你会在目标表中获得锁定。

因此,如果没有其他人正在写入目标表,并且一次只运行一个程序副本,就永远不会陷入僵局。

当两个(或更多)进程尝试执行永远无法完成的冲突事件时,会发生死锁。通常,这涉及以不同的顺序更新同一对行,但它可能取决于您的表结构。

要考虑的想法:

  • 使用外部锁(To innodb)将进程序列化为多个副本
  • 将此事务的事务隔离模式更改为READ_COMMITTED - 如果您了解这意味着什么并且可以容忍它。
  • 在一次交易中减少工作量(更频繁地提交)

您可以在死锁后立即使用SHOW ENGINE INNODB STATUS查看死锁所涉及的事务。

您应该能够看到其他过程是什么以及他们在做什么。考虑打开常规日志或使用其他调试技术。

请务必在非生产系统中进行任何测试!

答案 1 :(得分:2)

您可以尝试使用INSERT DELAYED,这就是它的作用:

  

当客户端使用INSERT DELAYED时,它立即从服务器获得正常,并且当该表未被任何其他线程使用时,该行排队等待插入。

如果您愿意看到处于混合状态的数据,则可以更改事务隔离级别

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- Problematic SELECT query goes here --
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

我从另一个SO那里得到了答案by Jon Erickson