MySQL有没有办法不加锁?

发布于 2024-10-02 07:26:45 字数 306 浏览 4 评论 0原文

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

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

据我所知,这听起来像是我的查询正在尝试获取当已经有锁时,锁定表。不过我承认我对表锁定或其工作原理一无所知。

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

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

I have a query that I run once a day that takes certain tables from my database and puts them into a single table so that I can quickly export the information in any format I require.

I am running into a problem however that gives me the following error: "SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction"

From what I understand it sounds like my query is trying to get a lock on the table when there already is a lock in place. However I confess that I do not know anything about table locking or how it works.

Really I am just trying to read the other tables and not write to them, is there a way that I can create the query but not request a lock?

My query is ridiculously long so that's why I did not post it. If there are certain parts that you need let me know and I can post them.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

尸血腥色 2024-10-09 07:26:45

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

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

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

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

我从另一个SO答案中了解到作者:Jon Erickson

You could try using INSERT DELAYED, here is what it does:

When a client uses INSERT DELAYED, it gets an okay from the server at once, and the row is queued to be inserted when the table is not in use by any other thread.

If you are willing to see data in a mixed state, you can change the transaction isolation level

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

I learned that one from another SO answer by Jon Erickson

两个我 2024-10-09 07:26:45

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

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

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

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

需要考虑的想法:

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

您可以在死锁发生后立即使用 SHOW ENGINE INNODB STATUS 查看死锁中涉及的事务正在执行的操作。

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

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

If you are in transaction isolation mode REPEATABLE_READ (which is the default), then selects should no create any locks. This is normal.

However if you're using insert ... select of course you'll get locks in the destination table.

So provided nobody else is writing to the destination table, AND there's at most one copy of your program running at once, you can never get a deadlock.

Deadlocks happen when two (or more) processes try to do conflicting things which could never complete. Normally this involves updating the same pair of rows in a differing order, but it can depend on your table structure.

ideas to consider:

  • Use an external lock (To innodb) to serialise the process against multiple copies
  • Change transaction isolation mode to READ_COMMITTED for this operation - if you understand what this means and can tolerate it.
  • Do less work in one transaction (commit more frequently)

You can see what the transactions involved in a deadlock were doing, using SHOW ENGINE INNODB STATUS, immediately after the deadlock.

You should be able to see what the other process(es) were and what they were doing. Consider turning the general log on or using other debug techniques.

Be sure to do any testing in a non-production system!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文