2012-12-02 108 views
2

我計劃寫下面的查詢:在INSERT/UPDATE查詢中原子多個MySQL子查詢?

INSERT INTO summary (user_id, total_points, count_operations) 
SELECT 
    15 AS user_id, 
    (SELECT SUM(points) FROM operations WHERE user_id = 15) AS total_points, 
    (SELECT COUNT(*) FROM operations WHERE user_id = 15) AS count_operations 
ON DUPLICATE KEY UPDATE 
total_points = VALUES(total_points), 
count_operations = VALUES(count_operations); 

是整個語句原子?即MySQL(使用MyISAM引擎)是否在內部鎖定了operations表?

MySQL是否有可能會按順序執行兩個子查詢,這可能會導致某些情況下(如果在該時間範圍內添加了新操作)total_pointscount_operations會不一致?

回答

1

MyISAM仍然使用table-level locks

這些存儲引擎通過總是在一個查詢開始,要求所有需要 鎖一次,並始終鎖定在相同的順序 表避免死鎖。權衡是這種策略減少了併發性;其他要修改表的會話必須等待 ,直到當前的DML語句結束。

所以其他想要更新你使用的表的進程必須等到你的事務完成。如果它在表「操作」上放置一個讀鎖定,則所有後續寫鎖定進入隊列並等待。

+0

好吧,如果我正確理解你的答案,MySQL將很可能鎖定操作表,所以我不應該擔心不一致的結果。缺點是整個表在操作期間被鎖定,這可能會降低併發性(與使用InnoDB使用行級鎖定相反)。 – quentinadam

+0

是的。如果鎖定是一個問題,請考慮切換到INNODB引擎。它行級鎖定。 –