0

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

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

据我了解,这听起来像是我的查询在已经有锁的情况下试图在表上获得锁。但是我承认我对表锁定或其工作原理一无所知。

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

我的查询太长了,所以我没有发布它。如果您需要某些部分,请告诉我,我可以发布它们。

4

2 回答 2

2

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

但是,如果您使用的是 insert ... select 当然,您将在目标表中获得锁。

因此,只要没有其他人正在写入目标表,并且您的程序最多一次运行一个副本,您就永远不会出现死锁。

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

要考虑的想法:

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

您可以在死锁之后立即使用 SHOW ENGINE INNODB STATUS 查看死锁中涉及的事务正在做什么。

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

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

于 2010-11-12T16:31:37.330 回答
2

您可以尝试使用INSERT DELAYED,它的作用如下:

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

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

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

我从Jon Erickson的另一个 SO 回答中了解到这一点

于 2010-11-12T16:43:42.743 回答