我想執行以下兩個MySQL語句:MySQL的:事務安全插入時行
1) SELECT * FROM table1 WHERE field1=val1 FOR UPDATE;
2) UPDATE table1 SET field2=val2 WHERE field1=val1;
重要的是,第二條語句正好改變了由第一條語句(沒有額外的行,沒有一個返回的行減)。因此,我使用auto_commit = false執行事務,並使用select語句的「for update」版本。
「For Update」會鎖定它返回的所有行,因此它們在執行第二條語句時處於原始狀態。但是插入呢?是否有可能另一個線程插入一個帶有field1 = val1 inbetween的新行,然後由第二個語句改變?
還有一個問題:如果第二條語句不改變行本身,但是做了類似下面的事情,它會有所作爲嗎?如果(3)與(1)在同一事務中,那麼確保兩個選擇都返回完全相同的元素嗎?
編輯:
我使用InnoDB和我讀到下一鍵鎖定和差距鎖定一些東西。 據我瞭解,在執行(1)時,InnoDB不僅會鎖定選定的行,還會鎖定訪問的索引。
所以我正確地說,如果我有一個索引在列「field1」上不會發生這個問題?如果沒有索引呢?那有什麼不同呢?
我想收集一些行,計算一些聚合(不是在sql中,但在應用程序代碼中),將聚合結果存儲在某處,然後將讀取的行標記爲「已完成」。確切地說,聚合的行被標記爲「完成」是非常重要的。 – Heinzi
@heinzi - 可能的,但它是一個固有的'硬'問題,定義了一個容錯版本。請創建一個新的問題,其中包含您當前的表格設置,以及問題空間的要求(當然還有目前的情況)。 –
謝謝。我認爲InnoDB提供了一些功能來防止這個普遍問題,但我不確定它們何時應用以及何時不起作用(請參閱上面的編輯)。 – Heinzi