2012-12-02 78 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引擎。它行级锁定。 –