0
确定这里就是正在发生的基本思想:MySQL的并发和相同的交易麻烦
begin transaction
some_data=select something from some_table where some_condition;
if some_data does not exists or some_data is outdated
new_data = insert a_new_entry to some_table
commit transaction
return new_data
else
return some_data
end
当多个进程以上同时执行的代码(如客户在同一时刻发出了很多相同的请求),将会插入大量'new_data',而实际上只需要一个'new_data'。
我认为这是一个非常典型的并发情况,但我仍然找不出一个体面的方法来避免它。我可以考虑的事情可能就像让一个工作进程执行select_or_insert作业,或者将隔离级别设置为Serializable(不可接受)。但对我而言,这两者都不令人满意。
PS:该数据库为MySQL,台引擎是InnoDB的,并且隔离级别是可重复读
是的,这部分解决了问题。但是如果some_data不存在呢?如果SELECT ... FOR UPDATE实际上什么都不返回会发生什么? –
@DeanWinchester:好点。另一种方法是使用[named locks](http://dev.mysql.com/doc/en/miscellaneous-functions.html);另一种方法是定义一个适当的'UNIQUE'键,然后试着'INSERT IGNORE',如果失败,则选择旧数据 - 根本不需要交易。 – eggyal
指定的锁似乎是我的案例的完美解决方案。凉! –