MySQL 中的过程和函数是原子的吗?

问题描述 投票:0回答:2

正如标题所说,MySQL 中的过程和函数是原子的吗?即想要类似的东西

for (..)
  <check_if_row_has_flag>
for (..)
  <update_row>

原子工作?

有趣的是,除了 2009 年的一个论坛帖子之外,我在 Google 上找不到太多相关内容。

mysql database stored-procedures atomic dbfunctions
2个回答
6
投票

不,存储过程不是原子的。

上面显示的伪代码存在竞争条件。第一个循环检查一行是否有标志,将返回答案,但除非您执行“锁定读取”,否则另一个并发会话可能会在您的过程读取该行后立即更改标志。 这就是

乐观锁

的效果。在您发出锁定行的语句之前,行不会被锁定。因此,即使在事务中,您也没有原子锁定。 MySQL支持的原子性是针对事务提交的。事务是原子的,因为事务期间所做的所有更改都会成功,否则所有更改都会回滚。其他会话无法看到您处于部分完成状态的交易。

回复以下评论:

您可以从应用程序调用事务中的过程:

START TRANSACTION; CALL MyProcedure(); COMMIT;

您甚至可以在过程正文中显式启动并提交一个事务(或连续的多个事务):

CREATE PROCEDURE MyProcedure() BEGIN START TRANSACTION; ...UPDATE, INSERT, DELETE, blah blah... COMMIT; END

但是过程本身不会隐式启动或提交事务。


0
投票
在MySQL中不是原子的。 *我们可以在过程中使用事务,但不能在函数中使用。

例如,您创建test

表,如下所示:

CREATE TABLE test (
  num int
);

然后,插入num为
2
的行,如下所示:

INSERT INTO test (num) VALUES (2);

然后,您创建
my_proc()
过程,将

num

更新为
5
,然后通过
SIGNAL语句
导致错误,如下所示:
DELIMITER $$ CREATE PROCEDURE my_proc() BEGIN UPDATE test SET num = 5; SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred'; END$$ DELIMITER ;

或者,您创建
my_proc()
过程,将

num

 更新为 
5
,然后导致事务中出现错误(
START TRANSACTION 和 COMMIT 语句
),如下所示:
DELIMITER $$ CREATE PROCEDURE my_proc() BEGIN START TRANSACTION; UPDATE test SET num = 5; SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred'; COMMIT; END$$ DELIMITER ;

然后,调用
my_proc()
会出现错误,但

num

不会回滚到
2
,如下所示:
mysql> CALL my_proc();
ERROR 1644 (45000): An error occurred
...
mysql> SELECT num FROM test;
+------+
| num  |
+------+
|    5 |
+------+

现在,您可以使用
DECLARE ... HANDLER 语句
和事务(

my_proc()

START TRANSACTION 语句)来使 COMMIT
 过程原子化,如下所示:
DELIMITER $$

CREATE PROCEDURE my_proc() 
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION
  BEGIN
    ROLLBACK;
  END;
  START TRANSACTION;
    UPDATE test SET num = 5;
    SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred';
  COMMIT;
END$$ 

DELIMITER ;

然后,调用
my_proc()
不会出现错误,因为错误是由

DECLARE ... HANDLER

语句处理的,然后
num
会回滚到
2
,如下所示:
mysql> CALL my_proc();
...
mysql> SELECT num FROM test;
+------+
| num  |
+------+
|    2 |
+------+


© www.soinside.com 2019 - 2024. All rights reserved.