2013-04-20 54 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