【问题标题】:Does MySQL queue queries?MySQL 是否排队查询?
【发布时间】:2013-04-13 16:43:30
【问题描述】:

如果有两个人同时向数据库发送相同的查询,而一个人让另一个查询返回不同的东西,会发生什么?

我有一家商店,那里只剩下一件商品。两个或更多人购买该商品,查询同时到达 MySQL 服务器。我的猜测是它只会排队,但如果是这样,MySQL 是如何选择第一个执行的,我可以对此产生影响吗?

【问题讨论】:

  • “我可以对此施加影响吗?”:- 是的。使用适当的事务隔离级别,例如可序列化

标签: php mysql sql database


【解决方案1】:

它们在用户请求时立即执行,因此如果有 10 个用户同时请求查询,那么将有 10 个查询同时执行。

任何事情都不会同时发生,CPU 也不会一次完成所有事情。它一次做一件事情(每个核心和/或线程)。如果有 10 个用户正在访问运行查询的页面,他们将以特定顺序“访问”服务器并按该顺序进行处理(尽管该顺序可能以毫秒为单位)。但是,如果一个页面上有多个查询,您不能确定一个用户页面上的所有查询都会在另一个用户页面上的查询开始之前完成。这可能会导致并发问题。

编辑:

运行SHOW PROCESSLIST 找到你想杀死的连接的ID .

SHOW PROCESSLIST 将为您提供所有当前正在运行的查询的列表。

来自here

MySQL 将在快速 CPU 上表现良好,因为每个查询都在单个线程中运行,并且不能跨 CPU 并行化。

【讨论】:

  • 好吧,如果有 10 个用户并且服务器有 10 个 CPU 并且所有 10 个用户导致 MySQL 以完全相同的毫秒运行查询(极不可能),那么理论上所有 10 个查询都可以在如果 MySQL 使用了所有 CPU 并且没有同步对同一行的访问,则同一时间。
  • 我不确定您是否完全正确。它不需要在完全相同的时间发生才能成为数据库中的问题。还有多核或 CPU(大多数服务器都有这些)。他们也不会在请求后立即执行。特别是如果有适当的隔离级别。
  • 这与网络服务器上有多少内核或 CPU 无关,重要的是 MySQL 服务器上发生了什么。
  • 这个答案让我感到困惑,首先你告诉我们可以同时执行 10 个查询,然后你说在同一时间什么都没有发生。然而你有 3 票赞成。
  • @echo_me 请查看 SQL 系统上的事务。您的回答具有误导性。当然,在 Menno Gouw 所描述的场景中存在并发问题。请相应地编辑它。例如,如果查询需要很长时间并且隔离级别允许脏读,会发生什么?这不是说结果会受到影响吗?
【解决方案2】:

考虑类似以下的查询:

UPDATE items SET quantity = quantity - 1 WHERE id = 100

无论 MySQL 服务器并行运行多少查询,如果运行 2 个这样的查询并且 id 100 的行有 quantity 1,那么默认情况下会发生这样的事情:

  1. 第一个查询锁定itemsid 为100 的行
  2. 第二个查询尝试做同样的事情,但行被锁定,所以它等待
  3. 第一个查询将 quantity 从 1 更改为 0 并解锁该行
  4. 第二个查询再次尝试,现在看到该行已解锁
  5. 第二个查询锁定itemsid 为100 的行
  6. 第二个查询将 quantity 从 0 更改为 -1 并解锁该行

【讨论】:

  • 如果这是真的,那我就不用担心了。对于我的示例,我只需要一个“WHERE 数量 > 0”。有人可以确认这是真的吗? Rid 似乎是合法的:D。同时我读了一些关于并发的文章。
【解决方案3】:

MySQL 中的查询是并行处理的。你可以read more about the implementation here

【讨论】:

    【解决方案4】:

    这本质上是一个并发问题。有一些方法可以通过使用事务来确保 MySQL 中的并发性。这意味着在您的 eshop 中,您可以确保像您描述的那样的竞争条件不会成为问题。有关 MySQL 中的事务,请参见下面的链接。

    http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-transactions.html

    http://zetcode.com/databases/mysqltutorial/transactions/

    根据您的隔离级别,两个并发查询会返回不同的结果。

    【讨论】:

    • 我不确定您的评论与我的回答是否相关。
    • +1 用于提及交易 - OP 应该为任何商店软件使用交易
    【解决方案5】:

    同时发送相同的查询

    查询并不总是并行运行

    这取决于数据库引擎。使用 MyISAM,几乎每个查询都获得表级锁,这意味着查询作为队列顺序运行。它们可以与大多数其他引擎并行运行。

    echo_me 说nothing happens at the exact same time and a CPU does not do everything at once

    这并不完全正确。 DBMS 有可能在具有多个 cpu 和多个网络接口的机器上运行。 非常不可能同时到达 2 个查询 - 但并非不可能,因此有一个互斥锁来确保配对/执行转换仅作为单个线程运行(执行 - 不一定是相同的轻量级工艺)。

    解决并发 DML 有 2 种方法 - 使用事务(每个用户有效地获得数据库的克隆)和当查询完成时 DBMS 尝试协调任何更改 - 如果协调失败,则 DBMS 滚动返回其中一个查询并将其报告为失败。另一种方法是使用行级锁定 - DBMS 识别将由查询更新的行并将它们标记为保留更新(其他用户可以读取每行的原始版本,但任何更新数据的尝试都将是被阻塞,直到该行再次可用)。

    您的问题是您有两个 mysql 客户端,每个客户端都检索到剩余一件库存的事实。由于(因为您提到 PHP)库存水平可能是在与随后的库存调整不同的 DBMS 会话中检索到的,这使情况更加复杂 - 您的事务不能跨越 HTTP 请求。因此,您需要在单个事务中重新验证在 DBMS 之外维护的任何事实。

    乐观锁定可以创建一个伪事务控制机制——你用时间戳和用户标识符标记你将要修改的记录(对于 PHP,PHP 会话 ID 是一个不错的选择)——如果你来修改它, 其他东西改变了它,那么你的代码就知道它之前检索到的数据是无效的。但是,这可能会导致其他并发症。

    【讨论】:

    • “其他用户可以读取每一行的原始版本,但任何更新数据的尝试都将被阻止,直到该行再次可用”如果您有 Serializable 隔离级别怎么办?我认为您在描述幻读,但事实并非如此。
    猜你喜欢
    • 2015-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 2020-03-08
    • 1970-01-01
    相关资源
    最近更新 更多