【问题标题】:MySQL - How to check if START TRANSACTION is activeMySQL - 如何检查 START TRANSACTION 是否处于活动状态
【发布时间】:2015-06-07 07:39:44
【问题描述】:

我注意到START TRANSACTION 自动COMMIT 之前的查询。由于这一点以及在整个事务结束之前调用了几个存储过程的事实,我需要检查我是否在START TRANSACTION 内。阅读手册后,我了解到START TRANSACTION 中的自动提交设置为 false,但看起来并非如此。我写了以下程序:

    CREATE DEFINER=`root`@`localhost` PROCEDURE `test_transaction`()
BEGIN

show session variables like 'autocommit';

start transaction;

show session variables like 'autocommit';

COMMIT;

show session variables like 'autocommit';

END

但是每个show session variables like 'autocommit'; 都显示 autocommit=ON 而我预计第二个是 autocommit=OFF。

如何检查我是否在 START TRANSACTION 中?

我需要执行此检查,因为我有需要 START TRANSACTION 的程序 1,然后它调用也需要 START TRANSACTION 的程序 2。但是让我们假设我有第三个过程 different_procedure 也需要调用 procedure2 但在这种情况下 different_procedure 不使用START TRANSACTION。在这种情况下,我需要 procedure2 来检查 START TRANSACTION 是否已启动。我希望这已经足够清楚了。

【问题讨论】:

    标签: mysql transactions autocommit


    【解决方案1】:

    您可以创建一个程序来利用只能在事务中发生的错误:

    DELIMITER //
    CREATE PROCEDURE `is_in_transaction`(OUT $transaction bool)
    BEGIN
        DECLARE oldIsolation TEXT DEFAULT @@TRANSACTION_ISOLATION;
        DECLARE EXIT HANDLER FOR 1568 BEGIN
            -- error 1568 will only be thrown within a transaction
            SET $transaction = true;
        END;
        -- will throw an error if we are within a transaction
        SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
        -- no error was thrown - we are not within a transaction
        SET TRANSACTION_ISOLATION = oldIsolation;
        SET $transaction = false;
    END//
    DELIMITER ;
    

    测试程序:

    set @within_transaction := null;
    set @out_of_transaction := null;
    
    begin;
        CALL is_in_transaction(@within_transaction);
    commit;
    
    CALL is_in_transaction(@out_of_transaction);
    
    select @within_transaction, @out_of_transaction;
    

    结果:

    @within_transaction | @out_of_transaction
    --------------------|--------------------
                      1 |                   0
    

    使用 MariaDB,您可以使用 @@in_transaction

    【讨论】:

    • 不幸的是,在当前的 MySQL 版本中,FUNCTION 方法不再起作用。请参阅bugs.mysql.com/bug.php?id=102531 以供参考。但是,使用 out 参数执行与 PROCEDURE 相同的操作似乎在 5.7 和 8.0 中仍然有效。
    • 另外,@@TX_ISOLATION 在 8.0 中被移除并被 @@TRANSACTION_ISOLATION 取代,参见 dev.mysql.com/doc/refman/5.7/en/…
    【解决方案2】:

    来自https://dev.mysql.com/doc/refman/5.5/en/implicit-commit.html

    事务不能嵌套。这是当您发出 START TRANSACTION 语句或其同义词之一时对任何当前事务执行的隐式提交的结果。

    我怀疑问题可以通过使用SET autocommit=0; 而不是START TRANSACTION; 来解决。如果 autocommit 已经为 0,则无效。

    另见Does setting autocommit=0 within a transaction do anything?

    【讨论】:

    • 谢谢,这可能是一个解决方案,但它很难看。我相信应该有一个干净的方法来检查你是否在“开始交易”中
    • @Stefano Giacone 你试过SELECT @@autocommit吗?
    • 是的,是一样的。 SET 自动提交=0;解决方案真的很糟糕,如果可能的话,我更喜欢更好的解决方案......
    • @Stefano Giacone 你有没有办法重写你的代码以免发生嵌套?
    • 这又是一种解决方法,我相信应该有一种方法可以检查“开始交易”是否已启动。我在问题中添加了有关我的代码的详细信息。
    猜你喜欢
    • 1970-01-01
    • 2020-01-11
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    相关资源
    最近更新 更多