为什么简单的MySQL更新查询偶尔需要几分钟?

时间:2010-02-12 15:07:57

标签: mysql mysql-management

我有一个庞大的数据库服务器,有许多非常相似的InnoDB数据库。我运行的查询通常只是更新小表中一行的时间戳。大多数情况下这需要1-2毫秒。有时,在晚上,可能在备份和maatkit复制工具运行时,这些查询中的一个或多个可能会在几分钟内显示“正在更新”。在此期间,其他查询(包括maatkit查询)似乎正常进行,并且似乎没有其他查询正在执行。我一直无法解释或解决这个问题。

我们在一对4路Xeon上使用mysql 4.1.22和gentoo 2.6.21,其中16GB的RAM和RAIDed驱动器用于存储。使用maatkit确认每晚复制,复制到位并运行良好。 InnoDB使用大部分RAM,而cpu通常是70-80%空闲。该表有大约100行,每行大约200字节。我在WHERE子句中尝试使用和不使用索引,但没有任何明显的更改。没有找到异常的日志消息(检查系统消息和mysql错误)。

还有其他人听说过这个吗?解决了这样的事情?有关如何调查的任何想法吗?

3 个答案:

答案 0 :(得分:1)

进行DML操作时,InnoDB会锁定行和索引间隙。

问题是它会锁定检查的所有行,而不仅仅是受影响的

比如说,如果你运行这个查询:

UPDATE  mytable
SET     value = 10
WHERE   col1 = 1
        AND col2 = 2

,锁定将取决于用于查询的索引:

  • 如果使用col1, col2上的索引,则只会锁定受影响的行

  • 如果使用col上的索引,则col1 = 1的所有行都将被锁定

  • 如果使用col2上的索引,则col2 = 2的所有行都将被锁定

  • 如果未使用任何索引,则会锁定所有行和索引间隙(包括PRIMARY KEY上的行,因此即使INSERTAUTO_INCREMENT也会锁定)

更糟糕的是,EXPLAIN中的MySQLDML操作不起作用,因此您必须猜测使用了哪个索引,因为优化程序可以选择任何索引它是最好的。

因此,您的复制工具和更新可能会同时锁定记录(正如您可以看到,即使WHERE条件不重叠,也可能会发生这种情况。)

答案 1 :(得分:0)

如果您在此查询挂起时可以访问服务器,请尝试执行“show innodb status”。您从中获得的部分数据是InnoDB表上所有活动连接/查询的状态。如果您的查询由于另一个事务而挂起,则会在那里显示。有锁数据here的样本。

同样,你提到它似乎发生了durint备份。你使用mysqldump吗?这将在转储处于活动状态时锁定表,以便转储的数据保持一致。

答案 2 :(得分:0)

使用回复中提供的一些信息,我们继续调查并在我们的服务器上发现了一些令人不安的行为。任何数据库中的任何表上的简单“检查表”都会导致简单的更新查询锁定在其他数据库和其他表中。我不知道为什么会发生这种情况,虽然我们无法在MySQL v5.1上重现它,所以我们打算升级我们的数据库服务器。

我不认为maatkit的mk-table-checksum会执行“检查表”,但它具有类似的效果。关闭此脚本可以显着减少问题,但我们相信如果没有此脚本,我们就无法生存。

我打算将此标记为我的问题的答案。谢谢你的帮助。