防止查询等待表级锁定的方法


10

将客户的数据库移至其他服务器后,我们遇到了问题。这应该会对站点的性能产生积极影响,但是MyISAM中的表锁定存在问题。(我听说过使用InnoDB代替MyISAM,但是我们不能在不久的将来更改引擎)。
我们可以将其发现为更新查询,该更新查询是由主持人在文章站点上激活评论时执行的。这是过程:

  • 更新查询已处理 SET status = 1 WHERE id = 5(已设置索引)
  • 页面的缓存文件被删除

此时,整个页面变慢。数据库本身忙了几分钟。我几次获取进程列表,并看到了大约60个不同选择查询的条目,它们都处于等待表级锁定的状态。

1.我不理解为什么表上的此更新article_comments会影响表article等待表级锁定的选择语句。在进程列表中,几乎所有等待查询都来自该表。我已经读过一个事实,即更新/插入优先于选择,并且这可能会导致此类问题,但是当注释被激活时,articles-table本身不会被更新,因此选择不应该等待。我错过了吗?
2.除了更改为InnoDB以外,还可以采取其他措施来防止此行为或至少获得更好的平衡吗?对于将数据库移动到新服务器之前没有出现此问题,我感到非常恼火。我猜有一些配置错误,但我不知道如何识别。


1
启用常规日志记录,并注意这些表之间的JOIN语句。当您选择SELECT时,它将创建一个隐式的READ LOCK。由于MYISAM不支持ROW LEVEL锁定,因此它将锁定在表级别。这种锁定可能是在旧服务器上发生的,但没人在看吗?比较my.cnf行与主机之间的行,尤其要确保正确调整了key_buffer。
randomx 2012年

在旧服务器上,我们还有其他一些性能问题,并且经常查看进程列表。主要有许多睡眠过程,但我们从未注意到等待的过程(我通常是在这台新服务器上第一次看到此信息)。我的同事复制了旧的my.cnf并将其值调整为新的现有硬件,但是条目并不多。我还比较了“ SHOW VARIABLES”的输出,但实际上不知道要看什么。明天我们将重新检查密钥缓冲区,感谢您的评论。
32bitfloat 2012年

我们最近有一个类似的问题。最初我们key_buffer_size设置为1GB。增加以10GB减少问题。
哈鲁克2012年

@里克·詹姆斯,谢谢。你今天救了我很多麻烦。您在亚马逊或其他地方有愿望清单吗?:)我将query_cache_limit设置为1024。现在没有锁定问题。首先,我是通过mysql客户端在变量中完成的。设置全局query_cache_limit = 1024; 现在,我将其写入my.cnf。这个解决方案使我有时间计划innodb迁移,而没有任何压力,谢谢。

Answers:


8

MyISAM存储引擎因对任何DML(INSERT,UPDATE,DELETE)执行全表锁定而臭名昭著。从长远来看,InnoDB肯定会解决该问题。

我写了关于使用MyISAM与InnoDB的利弊的文章

关于您当前的问题,这是一个可能的情况:

  • article并且article_comments都是MyISAM表
  • article_comments有一个或多个索引status作为列
  • 的索引页更新article_comments缓存在MyISAM密钥缓冲区(大小由key_buffer_size)中,从而导致旧索引页超出MyISAM密钥缓冲区
  • 您有SELECT查询,它们在article和之间执行JOINarticle_comments

在我建议的情况下,article由于必须等待article_comments从任何DML中释放出来(在这种情况下为UPDATE),因此可以阻止针对表的SELECT 不允许写入操作


感谢您的回答(以及链接),您的情况是真实的。我没有意识到大多数精选文章的确加入了注释表(或者换句话说,在phpmyadmin的进程列表中看到了不完整的语句)。您知道防止短期等待查询的短期解决方案吗?我已经在特定语句中使用“ UPDATE LOW_PRIORITY”进行了尝试,但是并没有进行明显的更改。我们确实会在将来更改为innodb,但我想知道当前是否有办法进行改进。
32bitfloat 2012年

最终解决方案:将表转换为InnoDB。请参阅我的文章dba.stackexchange.com/a/9422/877,了解如何将MyISAM转换为InnoDB
RolandoMySQLDBA 2012年

7

此时,整个页面变慢。数据库本身忙了几分钟。

闻起来像您有很大的Query_cache吗?

mysql> SHOW VARIABLES LIKE 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 16777216 | -- Not over 50M
| query_cache_type             | DEMAND   | -- Only if using SQL_CACHE
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

对于具有大量写入的生产系统,您也可以关闭query_cache。

所有当query_cache对于给定的表项将被清除任何写操作发生于该表。QC越大,此任务就越慢。

MyISAM使用“表级别”锁。读取和写入不能同时发生(在同一表上)。粗暴,但有效。


1
嗯,是。我们有大约64M的缓存大小。感谢您提供的新信息,但是,在旧服务器上,我们拥有相同的值,而我们没有注意到表锁。我们已经开始转移到InnoDB了,但是这个事实仍然是个谜...
32bitfloat,2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.