我有一个庞大的数据库服务器,有许多非常相似的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错误)。
还有其他人听说过这个吗?解决了这样的事情?有关如何调查的任何想法吗?
答案 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
上的行,因此即使INSERT
列AUTO_INCREMENT
也会锁定)
更糟糕的是,EXPLAIN
中的MySQL
对DML
操作不起作用,因此您必须猜测使用了哪个索引,因为优化程序可以选择任何索引它是最好的。
因此,您的复制工具和更新可能会同时锁定记录(正如您可以看到,即使WHERE
条件不重叠,也可能会发生这种情况。)
答案 1 :(得分:0)
如果您在此查询挂起时可以访问服务器,请尝试执行“show innodb status”。您从中获得的部分数据是InnoDB表上所有活动连接/查询的状态。如果您的查询由于另一个事务而挂起,则会在那里显示。有锁数据here的样本。
同样,你提到它似乎发生了durint备份。你使用mysqldump吗?这将在转储处于活动状态时锁定表,以便转储的数据保持一致。
答案 2 :(得分:0)
使用回复中提供的一些信息,我们继续调查并在我们的服务器上发现了一些令人不安的行为。任何数据库中的任何表上的简单“检查表”都会导致简单的更新查询锁定在其他数据库和其他表中。我不知道为什么会发生这种情况,虽然我们无法在MySQL v5.1上重现它,所以我们打算升级我们的数据库服务器。
我不认为maatkit的mk-table-checksum会执行“检查表”,但它具有类似的效果。关闭此脚本可以显着减少问题,但我们相信如果没有此脚本,我们就无法生存。
我打算将此标记为我的问题的答案。谢谢你的帮助。