给定连接上的慢 MySQL 查询何时会影响其他连接?

Posted

技术标签:

【中文标题】给定连接上的慢 MySQL 查询何时会影响其他连接?【英文标题】:When does a slow MySQL query on a given connection affect other connections? 【发布时间】:2012-07-01 19:10:40 【问题描述】:

我想我对此有一个基本的了解,但我希望有人能给我更多的细节,因为我有兴趣了解更多关于数据库性能的信息。

假设我有一个非常大的数据库,有数百万个条目,该数据库支持许多连接。由于数据太多,对数据库进行简单查询会很慢。我试图准确了解给定连接上的查询何时开始对在其他连接上运行的查询的性能产生直接影响。

如果一个连接锁定了某些元素,我知道这将阻止运行需要这些元素的其他连接的查询。例如做:

SELECT FOR UPDATE

将锁定您选择的内容。

当你做一些简单的事情时会发生什么:

SELECT COUNT(*) FROM myTable

假设我们有一个包含十亿行的表,因此运行计数将需要一些时间(在 innodb 上运行)。它会影响在其他连接上运行的查询吗?

如果使用 SELECT 和 JOIN 选择大量数据怎么办,例如:

SELECT * FROM myTable1 JOIN myTable2 ON myTable1.id = myTable2.id;

对于其他查询是否有连接锁定?

我发现很难知道哪些查询会对在其他连接上运行的查询的性能产生直接影响。

谢谢

【问题讨论】:

【参考方案1】:

有不同的角度:

行锁定:如果您调整架构,则不应发生这种情况,因此您应该忘记它 真正的性能问题和瓶颈。在我们的例子中,是附带影响。

关于这第二点,问题主要分为3个方面:

磁盘读取 内存使用(缓冲区) CPU 使用率。

关于磁盘读取:您将检索的数据(以字节为单位)越多,硬盘驱动器就越繁忙,并且会减慢使用它的任何其他活动。减小选定行的大小以避免磁盘开销。

关于内存使用:mysql 管理一个内部缓冲区,在某些情况下可能会卡住。我对此了解的不够多,无法给你一个正确的答案,但我知道这绝对是你应该关注的事情。

关于cpu使用情况:基本上cpu会忙的时候

必须计算(连接、准备语句、算术...) 必须完成所有外围工作:例如将字节从磁盘移动到内存。 优化查询以减少 CPU 开销。 (听起来很傻,但是,无论如何,这总是问题所在......)

那么,现在什么时候知道什么时候会产生附带效应?通过分析您的硬件... 如何配置文件?

绝对分析:使用SHOW INNODB STATUSSHOW PROFILE 获取有关主mysql 硬盘、cpu 和内存监视的有用信息。 相对分析:使用您最喜欢的操作系统分析器。例如在 windows xp 下,您可以使用伟大的perfmon.exe 并监视mysql 进程的PRIVATE BYTESVIRTUAL BYTES。我说的是相对的,因为毕竟如果查询在您的计算机上很耗时,那么它可能不在 NASA 系统上......

希望对你有帮助,问候。

【讨论】:

谢谢,这让对硬件方面的理解更加清晰。但是,从第一个角度来看,我仍然无法正确理解我如何确信给定的查询会或不会导致锁定...... 如果您不更新或删除(注意 CASCADE 或 TRIGGERS 副作用)事务中的给定行,或者使用 LOCK mysql 命令明确设置自己的锁,则没有锁。一个简单的 SELECT 永远不会锁定一行。另外,请注意MYISAM引擎,据我所知,它很容易锁定整个表! 是的,MyISAM 在更新/删除时执行表级锁定。如果 where 子句使用唯一键或主键,InnoDB 锁会执行行级锁,否则它可能会执行块级锁或表锁。【参考方案2】:

这是一个非常笼统的问题,因此很难给出准确的答案。

您可以将数据库视为共享资源池;特别是因为你的数据库运行的底层硬件有物理限制。大多数情况下,您看到诸如选择查询之类的东西会对其他查询造成性能影响的原因是,它们都在竞争使用诸如磁盘 IO 或 RAM 访问或 CPU 时间之类的底层物理资源,并且没有足够的时间来解决.

因此,您将看到的实际结果在很大程度上取决于数据库的物理硬件和配置设置。

例如,在您选择的示例中,变量可能是:查询需要的数据是否已经在 RAM 中?它可以通过索引有效地查找行吗?如果它必须做 IO,有多少其他查询要求从磁盘读取数据?您是否使用二级索引并且必须进行多次读取?数据库是否在进行预读以缓冲其他页面?查询是否导致顺序或随机 io?是否有任何更新锁定了数据?物理硬件可以支持多少读取 IO?

您必须为当前正在执行的所有查询回答所有这些问题,才能知道它们是否会影响其他查询的性能。

这就是 DBA 存在的原因。繁忙的数据库是一个复杂的系统,它涉及大量不同操作的交互,所有这些操作都受到数以千计的可能变量的影响。

因此,您通常要做的就是优化您可以控制以及您知道如何控制的事物(硬件、mysql 配置、架构和索引),然后在系统运行时开始测量系统以了解实际情况。

因此,在您的情况下,我会说专注于简单地单独优化您的查询会更有帮助。他们执行得越快,他们可能使用的资源就越少,他们对其他人的影响就越小。然后你学会分析系统。只看一件很慢的东西,然后问“为什么这么慢?”然后修复它。这就是优化过程。

但是,在您使用 SELECT ... FOR UPDATE 编写的第一种情况下,显式锁可能并且将会是很大的性能问题。小心那些。

【讨论】:

感谢您的回答,您能给我一些关于如何知道 SQL 查询是否会导致阻塞问题的建议吗?您如何立即知道 SELECT ... FOR UPDATE 会导致问题?还有哪些其他 SQL 命令会导致类似问题? SELECT FOR UPDATE 为 InnoDB 锁定行,或为 MyISAM 锁定表。它在事务中用于获取您将处理并最终更新的数据的锁定。它还可能锁定不适合 where 子句的行,我不太明白为什么它们也被锁定(当我读到这篇文章时),但这与它们是 where 子句中的部分候选者而没有被释放有关。 【参考方案3】:

读取查询仅受其他查询的隔离级别影响。他们自己不会永远挡住桌子。

隔离级别是指定的事务安全模式。如果使用锁定的另一个查询不允许脏读,则您的读操作将一直保持到其他查询完成写入或解锁。

MVCC 是一种允许数据库在需要更新或删除数据时创建新版本数据的机制。这意味着当您开始读取当前版本的数据时,它的数据不会受到未来更新/删除的影响。

当您开始写入当前数据时,尽管数据当前正在被另一个进程读取,您实际上是在其他地方写入新内容并将它们标记为最新版本。这最终意味着写入过程没有阻塞(至少不是因为读取过程)。

【讨论】:

谢谢,这很有意义,但是如何知道给定的查询是读取。如果您有一个带有如上所示连接的读取查询,它有很多工作要做,它从连接 A 开始,然后连接 B 上的另一个查询更新 A 当前尝试选择的数据中的一行.发生什么了? B会等A吗? A是否必须停止并重新开始,因为B已经做出了改变?有关这方面的更多信息将是最有帮助的。

以上是关于给定连接上的慢 MySQL 查询何时会影响其他连接?的主要内容,如果未能解决你的问题,请参考以下文章

mysql中的慢查询会不会影响速度

怎样用 Navicat for MySQL 连接上Linux服务器上配置好的mysql数据库

学会读懂 MySql 的慢查询日志

Django 慢查询:将 django 过滤语句连接到数据库日志中的慢查询

用 Laravel/Eloquent 为 Yajra DataTables 编写连接查询的慢 MySQL

Oracle的连接与会话