简体   繁体   English

MySQL并发和相同事务的麻烦

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM