如果您尝试更新正在查询的表,MySQL会怎么做?

时间:2009-01-12 11:53:32

标签: mysql performance

我的查询非常慢,我需要不时在MySQL数据库上运行。

我发现在查询完成之前,会阻止尝试更新正在查询的表。

我想这是有道理的,否则查询的结果可能会不一致,但对我来说并不理想,因为查询的重要性远低于更新。

所以我的问题实际上有两个部分:

  1. 出于好奇,MySQL在这种情况下究竟做了什么?它是否在查询期间锁定表格?或者在更新之前尝试锁定它?

  2. 有没有办法让慢查询不阻塞?我猜选项可能是:

    • 在需要更新时终止查询。
    • 在更新发生之前的表副本上运行查询
    • 只是让查询出错。
  3. 有人对此有任何想法吗?

5 个答案:

答案 0 :(得分:5)

听起来您正在使用MyISAM表,它使用表级锁定。在这种情况下,SELECT将在表上设置共享锁。然后UPDATE将尝试请求独占锁定和阻塞,并等待SELECT完成。一旦完成,UPDATE将正常运行。

MyISAM Locking

如果您切换到InnoDB,那么您的SELECT默认情况下不会设置锁定。没有必要像其他人推荐的那样更改事务隔离级别(InnoDB默认可重复读取,并且不会为SELECT设置锁定)。 UPDATE将能够同时运行。 InnoDB使用的多版本与Oracle处理这种情况的方式非常相似。 SELECTs设置锁定的唯一时间是,如果您在可序列化的事务隔离级别中运行,则查询具有FOR UPDATE / LOCK IN SHARE MODE选项,或者它是某种写入语句的一部分(例如INSERT。 ..SELECT)并且您正在使用基于语句的二进制日志记录。

InnoDB Locking

答案 1 :(得分:1)

出于select语句的目的,您应该发出:
    SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
连接上的命令,导致后续的select语句无锁定地运行 不要使用'SELECT ... FOR UPDATE',因为它肯定会锁定受select语句影响的表行 msql事务isloation级别的完整列表是in the docs

答案 2 :(得分:1)

首先,你需要知道你正在使用什么引擎(MySam或InnoDb)。

这显然是一个交易问题。

看看 13.4.6部分。 mysql手册中的SET TRANSACTION语法

答案 3 :(得分:0)

我不知道MySQL,但这听起来像是交易问题。 您应该能够在选择查询中将事务类型设置为Dirty Read。

这不会给你正确的结果。但它不应该被阻止。

最好是让第一个查询更快。做一些分析并检查是否可以通过正确的独立来加速它等等。

答案 4 :(得分:0)

UPDATE LOW_PRIORITY ....可能会有所帮助 - mysql文档不清楚这是否会让请求更新的用户继续,并且更新发生在可能的时候(我认为这是发生的事情)或用户是否有等待(这会比现在更糟糕......),我不记得了。

您使用的是哪种表类型?如果您使用的是MyISAM,切换到InnoDB(如果可以的话 - 它没有全文索引)会为这类事情开辟更多选项,因为它支持事务功能和行级锁定。