2013-04-20 41 views
4

如果有两个人同时向数据库发送相同的查询并且另一个查询返回不同的内容,会发生什么情况?MySQL队列查询吗?

我有一家商店,还有一件商品。两个或两个以上的人购买物品,并且查询在MySQL服务器上同时到达。我的猜测是它只会排队,但如果是这样的话,MySQL如何挑选第一个执行并且我可以对此产生影响?

+1

“我可以对此有影响吗?”: - 是的。使用适当的事务隔离级别,如可序列化的 – 2013-04-20 10:03:10

回答

5

同时

查询不总是并行运行

这取决于数据库引擎发送相同的查询。使用MyISAM,几乎每个查询都会获取一个表级锁,这意味着查询按顺序作为队列运行。大多数其他发动机可以并行运行。

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

这是不完全正确。数据库管理系统有可能在具有多个CPU的机器上运行,并且具有多个网络接口。它是非常不可能的是2个查询可能同时到达 - 但并非不可能,因此存在一个互斥来确保配对/执行转换仅作为单个线程运行(执行 - 不必是相同的轻量级进程) 。

有两种解决共存DML的方法 - 要么使用事务(每个用户有效获取数据库的克隆),并且在查询完成时DBMS会尝试协调任何更改 - 如果对帐失败,则DBMS回滚其中一个查询并报告失败。另一种方法是使用行级锁定 - DBMS识别将由查询更新的行并将其标记为预留用于更新(其他用户可以读取每行的原始版本,但是尝试更新数据的任何尝试都将是阻止直到该行再次可用)。

你的问题是,你有两个mysql客户端,其中每个客户端都检索到有一个库存项目的事实。 (因为你提到PHP),这个库存水平可能已经在不同的DBMS会话中被检索到,而不是随后的库存调整 - 你不能有一个跨越HTTP请求的事务。因此,您需要在单个事务中重新验证在DBMS外部维护的任何事实。

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

+0

“其他用户可以读取每行的原始版本,但是任何尝试更新数据的操作都将被阻止,直到该行再次可用”如果您具有可序列化的隔离级别,该怎么办?我认为你描述的并不是这种情况。 – idipous 2013-04-20 19:04:09

4

它们在用户请求它时立即执行,因此如果有10个用户在同一时间请求查询,则会同时执行10个查询。

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

编辑:

运行SHOW PROCESSLIST找到你想杀死 的connecton的ID。

SHOW PROCESSLIST会给你一个当前正在运行的查询的列表。

from here

由于每个查询在单个线程中运行,并且不能在CPU之间并行执行,所以MySQL将在快速CPU中表现良好。

+0

那么,如果有10个用户,并且服务器有10个CPU,并且所有10个用户都会导致MySQL在完全相同的毫秒(极不可能)运行查询,那么理论上所有10个查询都可以运行同时如果MySQL使用了所有的CPU并且没有同步对同一行的访问。 – rid 2013-04-20 10:11:21

+0

我不确定你是否完全正确。它不需要在同一时间发生,因为它是数据库中的问题。另外多核心或CPU(大多数服务器都有这些)。此外,他们不会尽快执行他们的要求。特别是如果有隔离级别的话。 – idipous 2013-04-20 10:11:40

+0

这不是关于网络服务器上有多少核心或CPU,重要的是MySQL服务器上发生了什么。 – 2013-04-20 10:17:11

2

考虑类似的查询到:

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

但是许多查询MySQL服务器并行运行,如果2级这样的查询运行,该行与 1 ,那么默认情况下会发生这样的事情:

  1. 的第一查询锁定在items行其中id是100
  2. 第二个查询试图做的相同,但该行被锁定,所以它等待
  3. 第一个查询从1改变所述quantity为0和解锁行
  4. 第二个查询再次尝试和现在看到的行被解锁
  5. 第二个查询锁定在items行其中id是100
  6. 第二个查询改变从0到quantity -1和解锁行
+0

如果这是真的,那么我不需要担心。对于我的例子,我只需要一个“WHERE数量> 0”。有人可以证实这是真的吗? Rid虽然看起来合法:D。同时我读了一些关于并发性的内容。 – Madmenyo 2013-04-20 10:15:23

+0

@MennoGouw,'WHERE quantity> 0'将起作用。 – rid 2013-04-20 10:16:04

2

这实际上是一个并发问题。有办法通过使用事务来确保MySQL的并发性。这意味着在您的eshop中,您可以确保所描述的竞争条件不会成为问题。请参阅以下关于MySQL中事务的链接。

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

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

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

+0

我不确定你的评论与我的答案相关。 – idipous 2013-04-20 10:14:04

+0

+1提交交易 - OP应该使用任何商店软件的交易 – 2013-04-20 10:18:37

+0

我想念你的帖子,对不起。 – Madmenyo 2013-04-20 10:22:07