2015-06-07 5 views
5

Ich habe festgestellt, dass START TRANSACTION automatisch COMMIT die vorherigen Abfragen. Aus diesem Grund und der Tatsache, dass ich mehrere gespeicherte Prozeduren vor dem Ende der gesamten Transaktion aufgerufen habe, muss ich überprüfen, ob ich in einem START TRANSACTION bin oder nicht. Beim Lesen des Handbuchs habe ich verstanden, dass Autocommit in einem START TRANSACTION auf false gesetzt ist, aber es sieht nicht so aus. Ich habe das folgende Verfahren geschrieben:MySQL - Wie überprüft man, ob START TRANSACTION aktiv ist

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 

Aber jede show session variables like 'autocommit'; zeigen autocommit = ON, während ich die zweite erwartete autocommit = OFF werden. Wie kann ich überprüfen, ob ich in einem START TRANSACTION bin?

Ich muss diese Prüfung durchführen, weil ich procedure1 habe, das START TRANSACTION benötigt, dann ruft es procedure2 auf, die auch START TRANSACTION benötigen. Aber nehmen wir an, ich habe eine dritte Prozedur different_procedure, die auch procedure2 aufrufen muss, aber in diesem Fall wird START TRANSACTION nicht verwendet. In diesem Szenario benötige ich procedure2, um zu überprüfen, ob START TRANSACTION initiiert wurde. Ich hoffe, das ist genug klar.

Dank

Antwort

1

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

Transaktionen können nicht verschachtelt werden. Dies ist eine Konsequenz der impliziten Festschreibung, die für jede aktuelle Transaktion ausgeführt wird, wenn Sie eine START TRANSACTION-Anweisung oder eines ihrer Synonyme ausgeben.

Ich vermute, dass das Problem mit SET autocommit=0; anstelle von START TRANSACTION; behoben werden kann. Wenn Autocommit bereits 0 ist, hat dies keine Auswirkungen.

Siehe auch Does setting autocommit=0 within a transaction do anything?

+0

Dank verwenden kann, dass eine Lösung sein, aber es ist hässlich. Ich glaube, es sollte einen sauberen Weg geben, um zu überprüfen, ob Sie sich in einer "Starttransaktion" befinden. –

+0

@Stefano Giacone Haben Sie versucht, SELECT @@ autocommit auszuwählen? –

+0

Ja, es ist dasselbe. Das SET-Autocommit = 0; Lösung es ist wirklich schrecklich, ich bevorzuge eine bessere, wenn möglich ... –

5

Sie können eine Funktion erstellen, die einen Fehler ausnutzen wird, die nur innerhalb einer Transaktion auftreten können:

DELIMITER // 
CREATE FUNCTION `is_in_transaction`() RETURNS int(11) 
BEGIN 
    DECLARE oldIsolation TEXT DEFAULT @@TX_ISOLATION; 
    DECLARE EXIT HANDLER FOR 1568 BEGIN 
     -- error 1568 will only be thrown within a transaction 
     RETURN 1; 
    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 TX_ISOLATION = oldIsolation; 
    RETURN 0; 
END// 
DELIMITER ; 

Testen Sie die Funktion:

set @within_transaction := null; 
set @out_of_transaction := null; 

begin; 
    set @within_transaction := is_in_transaction(); 
commit; 

set @out_of_transaction := is_in_transaction(); 

select @within_transaction, @out_of_transaction; 

Ergebnis :

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

Mit MariaDB können Sie @@in_transaction