0

好的,这是正在发生的事情的基本想法:

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”,而实际上只需要一个。

我认为这是一个非常典型的并发场景,但我仍然无法找到一种体面的方法来避免它。我能想到的事情可能就像让一个工作进程来完成 select_or_insert 工作,或者可能将隔离级别设置为可序列化(不可接受)。但两者都让我不太满意。

PS:数据库是mysql,表引擎是innodb,隔离级别是可重复读

4

1 回答 1

0

在您的初始SELECT,使用SELECT ... FOR UPDATE.

这确保了在事务提交(或回滚)之前,记录被锁定以防止其他客户端读取它,因此他们等待SELECT命令并且不会继续执行其余逻辑,直到第一个客户端完成其UPDATE.

请注意,您将需要条件中ROLLBACK的事务else,否则锁将继续阻塞,直到连接断开。

于 2012-05-29T18:49:40.847 回答