MySql:插入行时的事务安全

MySql:插入行时的事务安全,mysql,sql,transactions,sqltransaction,Mysql,Sql,Transactions,Sqltransaction,我想执行以下两条MySQL语句: 1) SELECT * FROM table1 WHERE field1=val1 FOR UPDATE; 2) UPDATE table1 SET field2=val2 WHERE field1=val1; 重要的是,第二条语句要准确地更改第一条语句返回的行(不增加行,也不减少行)。因此,我使用auto_commit=false执行事务,并使用select语句的“for update”版本 “For Update”锁定它返回的所有行,因此在执行第二条语句时

我想执行以下两条MySQL语句:

1) SELECT * FROM table1 WHERE field1=val1 FOR UPDATE;
2) UPDATE table1 SET field2=val2 WHERE field1=val1;
重要的是,第二条语句要准确地更改第一条语句返回的行(不增加行,也不减少行)。因此,我使用auto_commit=false执行事务,并使用select语句的“for update”版本

“For Update”锁定它返回的所有行,因此在执行第二条语句时它们处于原始状态。但是插入呢?是否有可能另一个线程插入了一个中间带field1=val1的新行,然后第二条语句会更改该行

还有一个问题:如果第二个语句不更改行本身,而是执行以下操作,是否会产生影响

3) INSERT INTO table2 (SELECT * FROM table1 WHERE field1=val1)
如果(3)与(1)处于同一事务中,那么是否确保两个选择返回完全相同的元素

编辑:

我正在使用InnoDB,我读了一些关于下一个键锁定和间隙锁定的资料。 据我所知,在执行(1)时,InnoDB不仅会锁定选定的行,还会锁定访问的索引


那么,如果我在“field1”列上有一个索引,这个问题就不会发生,我说的对吗?如果没有索引怎么办?那有什么不同吗?

我不能完全谈论mySQL的案例,但我相当怀疑。唯一可以从中选择的内容是。。。对于更新(显示),要做的是防止其他事务被删除。 它不限制将来的语句-如果在
UPDATE
语句运行之前插入了另一行(由另一个事务),它也将被更新。
不用说,你的第三句话也会成为同样问题的牺牲品


你到底想在这里做什么?有可能有另一种方法来实现这一点。例如,如果有某种类型的“insertedAt”时间戳,您可以将其作为一个附加条件添加进去。

我想收集一些行,计算它们的聚合(不是在sql中,而是在应用程序代码中),将聚合结果存储在某处,然后将读取的行标记为“完成”。将聚合的行准确地标记为“完成”是至关重要的。@heinzi-可能,但定义容错版本本身就是一个“困难”的问题。请创建一个新问题,其中包含您当前的表格设置,以及您的问题空间要求(当然,还有您到目前为止的问题)。谢谢。我认为InnoDB提供了一些功能来防止这个一般性问题,但我不确定它们什么时候适用,什么时候不起作用(请参见上面的编辑)。我无法真正回答您的编辑,但我认为这不会阻止插入额外的行。在这一点上,您同样运气不佳。就我个人而言,我宁愿少依赖于特定于数据库的机制,而更多地依赖于更具可移植性、更好的容错性、并且可能不需要索引才能实际工作的通用设计(而不仅仅是使其性能更好)。