我有一个程序任务来执行表的一致更新。为简单起见,我将讨论虚拟表以显示这个想法。所以我有两个表:user
和note
。
note
有id
(主键自动增量)和user_id
(外键),number
和next_number
。
number
是一些用户注释。如果这是最新用户的注释,则next_number
可以等于0
,或者可以等于下一个用户注释的数量(如指向C ++链接列表中下一个节点的指针)。
因此每个用户都有从1到n编号的注释。
现在有两个流程( Proc1 和 Proc2 )需要为同一用户的表note
插入行。
因此,每个进程都启动一个事务,检索最新用户注释的number
,然后执行一些其他操作,并插入number
增加到1的新行。
两个流程( Proc1 和 Proc2 )是否有可能在其交易中检索相同的number
(比如第一个流程)会在第二个流程执行SELECT
和INSERT
语句之前执行UPDATE
语句吗?
例如:
SELECT number FROM note WHERE user_id = 1 AND next_number = 0
- 检索到的号码 5 SELECT number FROM note WHERE user_id = 1 AND next_number = 0
- 检索到的数字 5 INSERT INTO note SET number = 6, next_number = 0, user_id = 1, text = 'Proc1 note'
INSERT INTO note SET number = 6, next_number = 0, user_id = 1, text = 'Proc2 note'
UPDATE note SET next_number = 6 WHERE number = 5
UPDATE note SET next_number = 6 WHERE number = 5
如果有可能,如何避免这种情况?
SELECT ... FOR UPDATE
会解决问题吗?
更新 - 简化我的问题
所以一般的问题是如果进程启动了一个事务,如何禁止其他MySQL会话与当前事务正在使用的行进行交互?
答案 0 :(得分:0)
您应该对此进行测试,以确保它正在做正确的事情,但第二个SELECT ... LOCK IN SHARE MODE
语句应该阻止,直到第一个完成。您还应该查看SERIALIZABLE事务隔离级别,该级别隐式设置此级别。