MySQL中的过程是原子的吗?

6bc51xsx  于 2024-01-05  发布在  Mysql
关注(0)|答案(2)|浏览(128)

正如标题所说,MySQL中的过程是原子的吗?

  1. for (..)
  2. <check_if_row_has_flag>
  3. for (..)
  4. <update_row>

字符串
原子地工作?
有趣的是,我在谷歌上找不到太多关于这方面的信息,除了2009年的一个论坛帖子。

zxlwwiss

zxlwwiss1#

不,存储过程不是原子的。
上面显示的伪代码有一个竞态条件。第一个循环,检查一行是否有标志,将返回一个答案,但除非你执行locking read,否则另一个并发会话可能会在你的过程读取该行后立即更改标志。
这就是乐观锁定的效果。除非你发出一个语句来锁定它们,否则它们不会被锁定。所以即使在事务中,你也没有原子锁定。
MySQL支持的原子性是针对事务提交的。事务是原子性的,因为在事务期间所做的所有更改都成功,否则所有更改都会回滚。其他会话无法看到处于部分完成状态的事务。
回复下面的评论:
您可以从应用调用事务中的过程:

  1. START TRANSACTION;
  2. CALL MyProcedure();
  3. COMMIT;

字符串
您甚至可以在过程的主体中显式地启动和提交一个事务(或连续的多个事务):

  1. CREATE PROCEDURE MyProcedure()
  2. BEGIN
  3. START TRANSACTION;
  4. ...UPDATE, INSERT, DELETE, blah blah...
  5. COMMIT;
  6. END


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

展开查看全部
ni65a41a

ni65a41a2#

默认情况下,procedure不是原子的,而function在MySQL中是原子的。* Atomic**意味着如果有错误就会回滚,我们可以在过程中使用transaction,而不能在函数中使用。
例如,创建test表,如下所示:

  1. CREATE TABLE test (
  2. num int
  3. );

字符串
然后,插入num2的行,如下所示:

  1. INSERT INTO test (num) VALUES (2);


现在,创建my_proc()过程,将num更新为5,然后通过SIGNAL statement导致错误,如下所示:

  1. DELIMITER $$
  2. CREATE PROCEDURE my_proc()
  3. BEGIN
  4. UPDATE test SET num = 5;
  5. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred';
  6. END$$
  7. DELIMITER ;


然后,调用my_proc()会得到错误,但num不会回滚到2,如下所示:

  1. mysql> CALL my_proc();
  2. ERROR 1644 (45000): An error occurred
  3. ...
  4. mysql> SELECT num FROM test;
  5. +------+
  6. | num |
  7. +------+
  8. | 5 |
  9. +------+


实际上,您可以使用my_proc()外部的事务将num回滚到2,如下所示。* 我的答案解释了如何使用my_proc()内部的事务将num回滚到2

  1. BEGIN;
  2. CALL my_proc();
  3. ROLLBAKC;


接下来,创建my_func()函数,将num更新为5,然后通过SIGNAL语句导致错误,如下所示:

  1. DELIMITER $$
  2. CREATE FUNCTION my_func() RETURNS INT
  3. DETERMINISTIC
  4. BEGIN
  5. UPDATE test SET num = 5;
  6. SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'An error occurred';
  7. RETURN NULL;
  8. END$$
  9. DELIMITER ;


然后,调用my_func()得到错误,然后num回滚到2,如下所示:

  1. mysql> SELECT my_func();
  2. ERROR 1644 (45000): An error occurred
  3. ...
  4. mysql> SELECT num FROM test;
  5. +------+
  6. | num |
  7. +------+
  8. | 2 |
  9. +------+

展开查看全部

相关问题