正如标题所说,MySQL 中的存储过程是原子的吗?即会像
for (..)
<check_if_row_has_flag>
for (..)
<update_row>
Run Code Online (Sandbox Code Playgroud)
原子地工作?
有趣的是,除了 2009 年的一个论坛帖子外,我在 Google 上找不到太多关于此的信息。
不,存储过程不是原子的。
您上面显示的伪代码具有竞争条件。第一个循环,检查一行是否有标志,将返回一个答案,但除非您执行锁定读取,否则另一个并发会话可能会在您的过程读取该行后立即更改标志。
这就是乐观锁的效果。在您发出锁定它们的语句之前,不会锁定行。所以即使在一个事务中,你也没有原子锁。
MySQL 支持的原子性是针对事务提交的。事务是原子的,因为在事务期间所做的所有更改都会成功,否则所有更改都会回滚。其他会话无法看到您处于部分完成状态的交易。
回复下面的评论:
您可以从您的应用程序调用事务中的过程:
START TRANSACTION;
CALL MyProcedure();
COMMIT;
Run Code Online (Sandbox Code Playgroud)
您甚至可以在过程主体中显式启动和提交事务(或多个串行事务):
CREATE PROCEDURE MyProcedure()
BEGIN
START TRANSACTION;
...UPDATE, INSERT, DELETE, blah blah...
COMMIT;
END
Run Code Online (Sandbox Code Playgroud)
但过程本身并不隐式启动或提交事务。