我想执行以下两个 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”上有一个索引就不会发生这个问题?如果没有索引怎么办?那不一样了吗?