[英]mysql concurrent and identical transactions trouble
OK here's the basic idea of what is happening: 好的,这是正在发生的事情的基本思想:
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
When multiple processes execute the code above simultaneously(like the client issues a lot of identical requests at a same time), a lot of 'new_data' will be inserted while actually only one is needed. 当多个进程同时执行上述代码时(例如客户端同时发出许多相同的请求),将插入许多“ new_data”,而实际上只需要一个。
I think it's a quite typical scenario of concurrency, but still I can't figure out a decent way to avoid it. 我认为这是一个非常典型的并发方案,但是我仍然想不出一种避免这种情况的合适方法。 Things I can think about maybe like having a single worker process to do the select_or_insert job, or maybe set the isolation level to Serializable(unacceptable).
我可以考虑的事情可能就像有一个工作进程来执行select_or_insert工作,或者将隔离级别设置为Serializable(不可接受)。 But neither is quite satisfactory to me.
但是,这两个都不令我满意。
PS: The database is mysql, table engine is innodb, and isolation level is repeatable read PS:数据库是mysql,表引擎是innodb,隔离级别是可重复读取
In your initial SELECT
, use SELECT ... FOR UPDATE
. 在初始
SELECT
,使用SELECT ... FOR UPDATE
。
This ensures that the record is locked against other clients reading it until the transaction has been committed (or rolled-back), so they wait on the SELECT
command and do not continue through to the rest of the logic until the first client has completed its UPDATE
. 这样可以确保记录被锁定,以防止其他客户端读取该记录,直到事务被提交(或回滚)为止,这样它们就等待
SELECT
命令,并且直到第一个客户端完成其事务后才继续执行逻辑的其余部分。 UPDATE
。
Note that you will need to ROLLBACK
the transaction in the else
condition, or else the lock will continue blocking until the connection is dropped. 请注意,您将需要在
else
条件下ROLLBACK
事务,否则锁将继续阻塞直到断开连接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.