5

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

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

4

5 回答 5

6

sending the same query at the same time

QUERIES DO NOT ALWAYS RUN IN PARALLEL

It depends on the database engine. With MyISAM, nearly every query acquires a table level lock meaning that the queries are run sequentially as a queue. With most of the other engines they may run in parallel.

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

That's not exactly true. It's possible that a DBMS could run on a machine with more than one cpu, and with more than one network interface. It's very improbable that 2 queries could arrive at the same time - but not impossible, hence there is a mutex to ensure that the paring/execution transition only runs as a single thread (of execution - not necesarily the same light weight process).

There's 2 approaches to solving concurent DML - either to use transactions (where each user effectively gets a clone of the database) and when the queries have completed the DBMS tries to reconcile any changes - if the reconciliation fails, then the DBMS rolls back one of the queries and reports it as failed. The other approach is to use row-level locking - the DBMS identifies the rows which will be updated by a query and marks them as reserved for update (other users can read the original version of each row but any attempt to update the data will be blocked until the row is available again).

Your problem is that you have two mysql clients, each of which have retrieved the fact that there is one item of stock left. This is further complicated by the fact that (since you mention PHP) the stock levels may have been retrieved in a different DBMS session than the subsequent stock adjustment - you cannot have a transaction spanning more than HTTP request. Hence you need revalidate any fact maintained outside the DBMS within a single transaction.

Optimistic locking can create a pseudo - transaction control mechanism - you flag a record you are about to modify with a timestamp and the user identifier (with PHP the PHP session ID is a good choice) - if when you come to modify it, something else has changed it, then your code knows the data it retrieved previously is invalid. However this can lead to other complications.

于 2013-04-20T10:47:21.867 回答
4

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

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

编辑:

运行SHOW PROCESSLIST以查找要杀死的连接的 id。

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

这里

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

于 2013-04-20T10:03:05.247 回答
3

考虑一个类似于以下的查询:

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

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

  1. 第一个查询将行锁定在itemswhere idis 100
  2. 第二个查询尝试做同样的事情,但是该行被锁定,所以它等待
  3. 第一个查询将quantity1 更改为 0 并解锁该行
  4. 第二个查询再次尝试,现在看到该行已解锁
  5. 第二个查询将行锁定在itemswhere idis 100
  6. 第二个查询将quantity0 更改为 -1 并解锁该行
于 2013-04-20T10:06:24.587 回答
2

This is essentially a concurrency question. There are ways to ensure concurrency in MySQL by using transactions. This means that in your eshop you can ensure that race conditions like the ones you describe won't be an issue. See link below about transactions in MySQL.

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

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

Depending on your isolation level different outcomes will be returned from two concurrent queries.

于 2013-04-20T10:07:38.243 回答
0

MySQL 中的查询是并行处理的。您可以在此处阅读有关实施的更多信息

于 2013-04-20T10:07:21.767 回答