MySQL - 如何使函数具有原子性?

3

我在我的数据库中有这个函数

CREATE FUNCTION BookBed (pPaciente varchar(255),
                                pHospital bigint(20)) RETURNS BOOLEAN
BEGIN
DECLARE NumLeitosDisponiveis INT;
DECLARE vReservaOK  BOOLEAN;
DECLARE dt TIMESTAMP;

 SET dt = (Select now());
 SET NumLeitosDisponiveis = (SELECT AVAILABLEBEDCOUNT FROM HOSPITAL WHERE ID = pHospital); 


 IF((SELECT NumLeitosDisponiveis) > 0) THEN 
 BEGIN
  START TRANSACTION;

  INSERT INTO RESERVATION(PERSON, HOSPITAL, DATE) VALUES (pPaciente, pHospital, dt);

  UPDATE HOSPITAL
    SET AVAILABLEBEDCOUNT = AVAILABLEBEDCOUNT - 1 
    WHERE ID = pHospital;

    SET vReservaOk = true;

    commit;
 END;
  ELSE 
    SET vReservaOk = false;     
  END IF;


 RETURN vReservaOK;

END;

在我的if-else语句的if部分,我希望以原子方式执行所有操作。我想使用START TRANSACTION命令,但它们在函数中被禁止,我找不到其他命令来执行它。
默认情况下,函数是原子的吗?如果不是,有没有办法实现它?
谢谢, Oscar 编辑:如果我必须使用函数,是否可能进行事务处理?

当你说“原子性(atomic)”时,你指的是什么? - Olaf
@Olaf:“原子性”意味着“保证不会被其他进程中断而发生”。就像你知道,在一个select语句和下一个语句之间,数据库是不能被更新的。 - Jay
您将在事务上下文中运行函数。其他事务上下文中发生的任何更改都不会在您的函数中可见,也不会影响其工作。数据库事务从定义上来说是原子性的。 - Olaf
你可以随时手动锁定表 - bobobobo
1个回答

0
使用带有输出参数的存储过程来返回操作状态。
DELIMITER //

CREATE PROCEDURE BookBed (
    pPaciente varchar(255),
    pHospital bigint(20),
    OUT oReservaOK boolean)
BEGIN
    DECLARE NumLeitosDisponiveis INT;
    DECLARE dt TIMESTAMP;

    SET dt = (Select now());
    SET NumLeitosDisponiveis =
        SELECT AVAILABLEBEDCOUNT FROM HOSPITAL WHERE ID = pHospital; 

    IF((SELECT NumLeitosDisponiveis) > 0) THEN 
    BEGIN
        START TRANSACTION;

        INSERT INTO RESERVATION(PERSON, HOSPITAL, DATE)
            VALUES (pPaciente, pHospital, dt);

        UPDATE HOSPITAL
            SET AVAILABLEBEDCOUNT = AVAILABLEBEDCOUNT - 1 
        WHERE ID = pHospital;

        SET oReservaOk = true;

        commit;
    END;
    ELSE 
        SET oReservaOk = false;     
    END IF;
END//

如果您在使用Hibernate调用存储过程时遇到问题,可以将事务逻辑移至Hibernate。也就是说,使用Hibernate构造开始、提交或回滚事务。 编辑 正如@bobobobo在评论中指出的那样,事务需要使用InnoDB引擎。

我遇到了问题,因为我现在使用Hibernate调用它并获取返回值时出现了问题。http://stackoverflow.com/questions/6497080/how-to-call-a-stored-procedure-using-hibernate 有没有办法在函数上使用事务? - JSBach
为什么你想在存储过程中启动事务?是调用该过程的事务“不够原子化”吗? - Olaf
@Oscar,不支持在MySQL函数内部进行事务处理。@Olaf,OP的问题是如何在函数内使用事务,在MySQL中这是不可能的;因此选项是使用存储过程代替。 - Xint0
请注意,您必须使用InnoDB表才能使其正常工作。"MyISAM不支持事务,也许永远都不会支持。" - bobobobo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接