2013-10-18 17 views
5

在每個基於InnoDB且啓用Autocommit的表的Mysql數據庫中,使用子查詢和/或連接的查詢是否是原子?在MySQL上連接插入/更新是一個原子操作嗎?

實例:

  • INSERT INTO users SELECT (x,y,z) FROM users, comments WHERE users.id = comments.user_id;(聯接)

  • UPDATE users, comments SET users.x = x1 WHERE users.age > 30;(聯接)

  • UPDATE users, comments SET users.x = x1, comments.y = y1 WHERE users.age > 30;(聯接)

  • UPDATE users, comments SET users.x = x1, comments.y = y1 WHERE users.id IN (SELECT id FROM users WHERE age > 30);(子查詢)

回答

5

包起來START TRANSACTION這樣

例子我理解像「是每一個本身就是這些查詢的原子操作的?」你的問題。那麼答案是「是」。另外兩個答案是正確的,當他們說你所有的陳述在一起都不是原子的。

數據庫原子性只意味着全部或全部沒有。它並不意味着數據的正確性。您的聲明是否成功。它與連接或子查詢無關。一種說法是一種說法,不管您的數據庫是否必須在內存或磁盤上使用臨時表。

事務只是告訴你的數據庫把多條語句當作一條語句。當其中一個語句失敗時,所有語句都會回滾。

這裏有一個重要的相關主題是isolation level。您可能需要閱讀這些內容。

編輯(回答評論):

這是正確的。只要它是一個有效的聲明,並且沒有電源故障發生或其他原因,爲什麼查詢可能會失敗,它正在完成。原子本身只是保證陳述正在完成或沒有完成。它保證了完整性,並且數據沒有損壞(導致寫操作沒有完成或什麼)。 它不保證數據的正確性。給定一個像INSERT INTO foo SELECT MAX(id) + 1 FROM bar;這樣的查詢,你必須確保通過設置正確的隔離級別,你沒有得到幻影讀取或任何東西。

+0

但是被原子化並不意味着沒有其他查詢會干擾查詢執行?在類似於「INSERT INTO用戶SELECT(x,y,z)FROM用戶,註釋WHERE users.id = comments.user_id AND條件」的查詢中,如果where條件滿足,那麼您將被授予更新權限後。這不正確嗎? –

+0

@DamianoBarbati更新了我的答案。 – fancyPants

+0

同意。我的假設是基於問題中的'sql語句',其中一行正在從另一個表複製,然後該行中的數據被更改。 –

0

我不癢,我會解釋你爲什麼。我對MySQL有一個很奇怪的問題。

想象一下,您有一張名爲「table1」的表格,其中包含一條記錄。列f1的值爲「A」。列f2的值爲「B」

Update table1 set f1 = CONCAT(f1,f2), f2 = 'C'; 

如預期的那樣,f1的最終值爲'AB'。

但是,如果你更改順序:

Update table1 set f2 = 'C', f1 = CONCAT(f1,f2); 

F1的終值是 '交流'。那就是:f2先改變,然後f1改變。

我的結論是更新操作顯然是非原子的。 f2首先被改變。在使用f2的更新值之後,f1被改變,而不是原來的值。

相關問題