2015-06-07 28 views
5

Ho notato che START TRANSACTION automaticamente COMMIT le query precedenti. Per questo motivo e per il fatto che ho diverse procedure memorizzate chiamate prima della fine dell'intera transazione, devo verificare se sono all'interno di uno START TRANSACTION o no. Leggendo il manuale ho capito che l'autocommit è impostato su false all'interno di un START TRANSACTION, ma non sembra così. Ho scritto la seguente procedura:MySQL - Come verificare se START TRANSACTION è attivo

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 

Ma ogni show session variables like 'autocommit'; spettacolo autocommit = ON mentre mi aspettavo il secondo ad essere autocommit = OFF.

Come posso verificare se sono all'interno di un START TRANSACTION?

Ho bisogno di eseguire questo controllo perché ho procedura1 che ha bisogno di START TRANSACTION quindi chiama procedura2 che anche bisogno di START TRANSACTION. Ma supponiamo di avere una terza procedura different_procedure che deve anche chiamare procedure2 ma in questo caso different_procedure non usa START TRANSACTION. In questo scenario ho bisogno della procedura2 per verificare se è stato avviato START TRANSACTION. Spero che questo sia abbastanza chiaro.

Grazie

risposta

1

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

Le transazioni non possono essere nidificate. Questa è una conseguenza dell'impegno implicito eseguito per qualsiasi transazione corrente quando si emette un'istruzione START TRANSACTION o uno dei suoi sinonimi.

Sospetto che il problema possa essere risolto utilizzando SET autocommit=0; anziché START TRANSACTION;. Se l'autocommit è già 0, non avrà alcun effetto.

Vedi anche Does setting autocommit=0 within a transaction do anything?

+0

Grazie, che può essere una soluzione, ma è brutto. Credo che ci dovrebbe essere un modo pulito per verificare se ci si trova all'interno di una "transazione iniziale" –

+0

@Stefano Giacone Hai provato 'SELECT @@ autocommit'? –

+0

Sì, è lo stesso. L'autocommit SET = 0; soluzione è davvero terribile, preferisco una migliore se possibile ... –

5

È possibile creare una funzione che sfrutterà un errore che può avvenire solo all'interno di una transazione:

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 ; 

Prova la funzione:

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; 

Risultato :

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

Con MariaDB è possibile utilizzare @@in_transaction

Problemi correlati