2011-10-12 28 views
6

例如,我有一列C1 value = 'clean'一排,和兩個不同的客戶端運行在同時此查詢:MyISAM和InnoDB中的單個mysql語句是否是原子的?

update T1 set C1 = 'dirty' where Id = 1 

不使用交易,是它無論保證發動機類型了的mysql_affected_rows()的價值將爲1爲一個客戶端和0爲另一個?

+1

如果您需要原子性,但不想使用InnoDB表[請參閱MySQL鎖定表](http://dev.mysql.com/doc/refman/5.1/en/lock-tables。html) – bobobobo

回答

11

Yes和No :-)

在這兩種情況下,access is serialised(假設你使用的事務引擎InnoDB的一樣),因爲他們打的同一行,所以它們不會互相干擾。換言之,報表原子。

但是,當您打開連接時,受影響的行數實際上取決於您的配置集。該page for mysql_affected_rows()有這樣一段話(我的粗體):

對於UPDATE語句,默認情況下,受影響的行值實際上是改變的行數。如果在連接到mysqld時將mysql_real_connect()指定爲CLIENT_FOUND_ROWS標誌,則受影響的行值爲行數「found」;即通過WHERE子句進行匹配。

而且從the mysql_real_connect page

CLIENT_FOUND_ROWS:返回的數求出(匹配的)行,而不是數量來改變行。

所以,在如何處理CLIENT_FOUND_ROWS發生方面進行配置,受影響的行爲:

UPDATE T1 SET C1 = 'dirty' WHERE id = 1 

什麼做的數據是否改變,只有哪些行相符。這兩個查詢都是1。

在另一方面,如果CLIENT_FOUND_ROWS組,第二個查詢實際上不會改變行(因爲它已經與「髒」填充),並且將具有零行計數。

如果你想要的相同的行爲,無論該設置(只顯示改變),你可以使用類似:

UPDATE T1 SET C1 = 'dirty' WHERE id = 1 AND C1 <> 'dirty' 
+0

你的意思是說單語句更新對於MyIASM不是原子的嗎? – Pacerier

+0

快速谷歌表明,只要你永遠不會殺死一個線程或查詢,MyISAM大多是原子。 http://bugs.mysql.com/bug.php?id=51193 –

+0

@sanmai:從http://dev.mysql.com/doc/refman/5.5/en/innodb-locks-set.html:一個鎖定讀取,UPDATE或DELETE通常會在處理SQL語句時掃描的每個索引記錄上設置記錄鎖。 – paxdiablo

3

MySQL是符合ACID,如果你使用像InnoDB的事務性存儲引擎。