Timer tra begin tran e commit

di il
11 risposte

Timer tra begin tran e commit

Ciao a tutti,
avrei bisogno di eseguire una update dei dati ma vorrei anche evitare di fare pasticci quindi farò delle prove con un DB di prova. Ma quello che mi chiedevo è: esiste un modo con sql di impostare un timer (ad esempio 120 secondi) tra il begin tran e il roll back o commit così che i quei 2 minuti io possa andare a verificare che i dati sono stati sovrascritti come voglio io?

Grazie mille a chi saprà aiutarmi

11 Risposte

  • Re: Timer tra begin tran e commit

    Non capisco perché ti serve un timer.

    Fai le tue operazioni con begin tran e senza commit/rollback;

    fai le tue verifiche ed alla fine decidi se fare commit o rollback

    Occhio però se lavori direttamente in produzione
    perché potresti bloccare l'accesso ad alcuni dati
    fino a che non chiudi la transazione in un modo o nell'altro

    HTH
  • Re: Timer tra begin tran e commit

    sspintux ha scritto:


    Non capisco perché ti serve un timer.

    Fai le tue operazioni con begin tran e senza commit/rollback;

    fai le tue verifiche ed alla fine decidi se fare commit o rollback

    Occhio però se lavori direttamente in produzione
    perché potresti bloccare l'accesso ad alcuni dati
    fino a che non chiudi la transazione in un modo o nell'altro

    HTH
    Perdona l'ignoranza ma non è molto tempo che traffico con sql
    Nella pratica dici di scrivere la query senza scrivere alla fine rollback o commit, verificare quello che mi interessa e rifare la query con il commit?
  • Re: Timer tra begin tran e commit

    EDIT .... oopss.
    scusa ho letto troppo di fretta.
    non devi rifare la query ; il committ/rollback la fai alla fine di quella fatta nella stessa finestra
    di esecuzione

    p.s.
    per scrupolo, verifica prima che il client che usi non esegua commit in automatico;
    SSMS non dovrebbe farlo di default .... ma vedi mai
  • Re: Timer tra begin tran e commit

    gpiazza874 ha scritto:


    Perdona l'ignoranza ma non è molto tempo che traffico con sql
    Non serve alcun timer.

    Devi impostare la SET TRANSACTION ISOLATION LEVEL (Transact-SQL)
    https://docs.microsoft.com/it-it/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver15
    Senza questa impostazione, qualsiasi transazione in corso blocca la lettura dei dati.

    Dopo aver impostato il livello ReadUncommitted puoi eseguire una query di INSERT o UPDATE senza eseguire il COMMIT e potrai leggere i dati modificati con una seconda query di select in cui scriverai:
     SELECT <elenco_campi> WITH (READ UCOMMITTED)
     FROM <Tabella>
     WHERE <condizioni>
    e potrai così analizzare il risultato ottenuto e decidere se fare il COMMIT o il ROLLBACK.
  • Re: Timer tra begin tran e commit

    LeoFar ha scritto:


    ....
    Dopo aver impostato il livello ReadUncommitted puoi eseguire una query di INSERT o UPDATE
    sinceramente , non so fino a che punto questo sia un buon consiglio adatto a tutte le situazioni.

    Si rischia di eseguire insert e/o update che possono potenzialmente coinvolgere dati non ancora consolidati.

    Direi che è meglio fare :
    eseguire insert/update al livello di isolamento previsto dall'applicazione
    e poi impostare il livello read uncommitted solo per visualizzare e controllare i dati non ancora committati
    se si desidera farlo da un'altra connessione.

    Ma quest'ultimo passaggio non è neanche necessario se, per esempio, si fa tutto dalla stessa finestra di query di SSMS in cui si è iniziata la transazione

    HTH
  • Re: Timer tra begin tran e commit

    sspintux ha scritto:


    sinceramente , non so fino a che punto questo sia un buon consiglio adatto a tutte le situazioni.

    Si rischia di eseguire insert e/o update che possono potenzialmente coinvolgere dati non ancora consolidati.
    Se affermi questo, cosa non vera, significa che non hai letto attentamente il mio post, oppure non l'hai capito.
    Non voglio fare polemica, ma solo puntualizzare quello che ho scritto.
    Poi ognuno è libero di fare come meglio sa e crede.
  • Re: Timer tra begin tran e commit

    LeoFar ha scritto:


    ...
    Non voglio fare polemica, ma solo puntualizzare quello che ho scritto.
    ...
    Neanche io voglio fare polemica @LeoFar
    ma, a mio modestissimo parere, questa tua frase dovresti spiegarla meglio

    LeoFar ha scritto:


    Dopo aver impostato il livello ReadUncommitted puoi eseguire una query di INSERT o UPDATE
  • Re: Timer tra begin tran e commit

    Salve,

    sspintux ha scritto:


    LeoFar ha scritto:


    ....
    Dopo aver impostato il livello ReadUncommitted puoi eseguire una query di INSERT o UPDATE
    sinceramente , non so fino a che punto questo sia un buon consiglio adatto a tutte le situazioni.

    Si rischia di eseguire insert e/o update che possono potenzialmente coinvolgere dati non ancora consolidati.

    Direi che è meglio fare :
    eseguire insert/update al livello di isolamento previsto dall'applicazione
    e poi impostare il livello read uncommitted solo per visualizzare e controllare i dati non ancora committati
    se si desidera farlo da un'altra connessione.

    Ma quest'ultimo passaggio non è neanche necessario se, per esempio, si fa tutto dalla stessa finestra di query di SSMS in cui si è iniziata la transazione

    HTH
    personalmente concordo con @sspintux...

    in ogni caso, "giocare" con il livello di isolamento a livello "applicativo" e non a livello puramente amministrativo/audit e' secondo me un tantino sopra le righe... non so quanto il gioco valga la candela...

    salutoni romagnoli..
    --
    Andrea
  • Re: Timer tra begin tran e commit

    sspintux ha scritto:


    ma, a mio modestissimo parere, questa tua frase dovresti spiegarla meglio

    LeoFar ha scritto:


    Dopo aver impostato il livello ReadUncommitted puoi eseguire una query di INSERT o UPDATE
    Mi sembra eloquente, visto che ho fatto l'esempio del codice ed ho anche linkato l'articolo di Microsoft.

    Comunque, cerco di spiegarlo meglio:
    quando si esegue una query con la clausola
    WITH (READ UCOMMITTED)
    , senza eseguire il COMMIT o il ROLLBACK diventa possibile interrogare i dati modificati per controllare il risultato, PRIMA che essi vengano scritti definitivamente nella tabella del database.

    Ovviamente, questa pratica si usa esclusivamente in fase di sviluppo della query per verificare che faccia quello per cui l'abbiamo progettata.

    Quindi non esiste alcun pericolo, come tu hai 'sospettato' perché è lo sviluppatore che decide se e quando usare il WITH (READ UCOMMITTED) nella query di test.
    Chiaramente, una volta verificato che la query fa il proprio lavoro non serve più usare WITH (READ UCOMMITTED).
    Se la verifica ha avuto esito positivo si può 'pubblicare' la query ed eseguire il COMMIT.

    Per inciso è l'unico modo per poter verificare i dati in una transazione senza che questi vengano aggiornati definitivamente.
    Infatti, senza il ReadUncommitted all'interno di una transazione i dati NON sono mai accessibili (quindi non verificabili) fin quando non si esegue il COMMIT.

    In teoria si potrebbe fare dei test su un database di prova (tengo sempre una copia dei miei database che aggiorno costantemente) ma si sa che non sempre i dati di test sono 'puliti' e qundi non si ha mai la certezza che tutto fili liscio.

    Io ho sempre utilizzato questo metodo con successo e grande soddisfazione.
  • Re: Timer tra begin tran e commit

    Salve a tutti..

    in questo caso specifico non comprendo comunque bene l'esigenza di un approccio fuori standard con livelli di isolamento diversi...
    (non scrivo codice DDL in quanto solitamente le policy del forum mi segano i messaggi, quindi metto DDL molto letterario )

    poniamo l'esempio "standard" di dover effettuare operazioni di "aggiornamento" su una tabella, e alla fine degli aggiornamenti fare verifiche di "non aver rotto niente" e da questo eseguire un rollback vs commit.

    ovviamente ricordiamo tutti che, all'interno dello stesso spid, quello che @LeoFar indica, cioe' di non poter accedere alle righe coinvolte nei lock imposti dal DML inserito in transazione, "non risulta vero"...
    dimostriamolo !
    
    -- pseudo code di DDL tabella:
    GeneraNuovaTabella dbo.t (
       Id int NOT NULL PRIMARY KEY,
       Dati int NOT NULL
       );
    GO
    INSERT INTO dbo.t
    	VALUES (1, 1), (2, 2), (3, 3);
    GO   
    
    a questo punto abbiamo la nostra operazione DML di aggiornamento...
    
    SELECT @@TRANCOUNT AS [tranCount];
    
    BEGIN TRAN
    	SELECT @@TRANCOUNT AS [tranCount];
    
    	UPDATE dbo.t
    		SET Dati = Dati + 100
    		WHERE Id <> 2;
    
    	SELECT * FROM dbo.t; -- <--- questo NON viene bloccato
    
    ROLLBACK
    
    SELECT @@TRANCOUNT AS [tranCount];
    SELECT * FROM dbo.t;
    
    --<--------------
    tranCount
    -----------
    0
    
    tranCount
    -----------
    1
    
    Id          Dati
    ----------- -----------
    1           101
    2           2
    3           103
    
    tranCount
    -----------
    0
    
    Id          Dati
    ----------- -----------
    1           1
    2           2
    3           3
    
    quindi resto del parere che "tutto questo giro" non risulta necessario, all'interno dell'esecuzione dell'operazione...

    Altro caso ovviamente e' il fatto di aprire una transazione in spid 51, lasciarla "appesa", e in spid 100 voler accedere alle righe coinvolte...

    quindi, nella finestra di SSMS, blocchiamo l'esecuzione di quanto sopra alla riga
    SELECT * FROM dbo.t; -- <--- questo NON viene bloccato

    non avendo chiuso la transazione, resta tutto appeso...

    Debug.Assert ("fino a qui siamo tutti d'accordo, vero??");

    in altra finestra di query, eseguiamo semplicemente
    
    SELECT @@TRANCOUNT AS [tranCount], @@SPID AS [spid];
    
    SELECT * FROM dbo.t;
    [code]
    
    il tranCount sara' == 0 in quanto questo comando NON ne imposta di esplicite, ma l'esecuzione restera' appesa in quanto stiamo utilizzando il livello di isolamento "standard", e cio' NON ci fa accedere alle righe/pagine/tabella bloccate...
    
    in questo triviale esempio, con impostazioni standard, SQL Server ha scelto un lock a livello di riga...
    [code]
    SELECT * FROM dbo.t
    	WHERE id = 2;
    --<-----------
    Id          Dati
    ----------- -----------
    2           2
    
    ed infatti ho accesso alla riga NON lockata...

    quindi, sempre a mio parere, quanto indicato da @LeoFar, ha senso SE vogliamo accedere a dati eventualmente lockati DA uno spid diverso dal "nostro"...

    in ogni caso, l'argomento NON e' assolutamente triviale...
    per chi desidera approfondire, consiglio la lettura dell'ottimo (e gratuito)
    https://www.red-gate.com/library/sql-server-concurrency-locking-blocking-and-row-versioning
    di Nostra Signora SQL Server miss Kalen Delaney

    salutoni romagnoli domenicali
    --
    Andrea
  • Re: Timer tra begin tran e commit

    Ciao Andrea,

    aqsl ha scritto:


    ...
    Nostra Signora SQL Server miss Kalen Delaney
    Sempre sia lodata

    aqsl ha scritto:


    ...
    Debug.Assert ("fino a qui siamo tutti d'accordo, vero??");
    ...
    Concordo non solo fino a qui ma in tutto e per tutto

    Mi permetto di aggiungere anche un esempio in cui questa frase :
    Dopo aver impostato il livello ReadUncommitted puoi eseguire una query di INSERT o UPDATE
    se interpretata secondo il senso comune causa incongruenza nei dati.

    Le scenario simula un aggiornamento 'a cuore aperto' della base dati, ovvero un aggiornamento mentre gli utenti usano l'app.

    Ci sono due tabelle : dbo.tbReadUncommited e dbo.tbToUpdate;

    dbo.tbToUpdate ha un solo record che deve memorizzare la somma di un campo di tutti i record in dbo.tbReadUncommited

    Dopo aver predisposto le create table e le insert iiniziali ( 01-Preparazione_Scenario_Dimostrativo)

    occorre aprire due diverse finestre di query in SSMS delle quali :

    una (02-Finestra_Dato_Fantasma) simula un utente delll'app che tenta di inserire
    in dbo.tbReadUncommited un dato di cui verrà fatto il rollback per un motivo qualsiasi

    e l'altra (03-Finestra_di_Insert_Update_Amministrativo)
    simula l'aggiornamento amministrativo ( 03-Finestra_di_Insert_Update_Amministrativo)

    L'incongruenza si genera eseguendo in rapida successione (e rispettando l'ordine seguente) il codice nelle finestre :

    02-Finistra_Dato_Fantasma (N.B: non devi aspettare che queta esecuzione sia terminata )
    03-Finestra_di_Insert_Update_Amministrativo

    Una volta terminate le esecuzioni nelle due finiestre il risultato incongruente si evidenzia eseguendo le query
    
    select * from dbo.tbToUpdate      ( contiene 11 quando il dato corretto dovrebbe essere 1)
    select * from dbo.tbReadUncommited 
    

    Seguono gli script
    N.B.
    alcune istruzioni DDL sono state scritte in pseudo T_SQL o sono state aggiunte delle XXX fittizie
    per bypassarre il filtro di sicurezza del forum per cui vanno corrette e tolte le XXX pena errore in SSMS.


    01-Preparazione_Scenario_Dimostrativo
    
    Create dbo.tbReadUncommited
    ( id int primary Key, Valore int)
    -- inserisco 1 record di test
    insert into dbo.tbReadUncommited (id, valore)values (1,1)
    
    -- nelle nostre intenzioni, questa deve contenere la somma del campo valore della tabella dbo.tbReadUncommited
    Create table dbo.tbToUpdate
    ( id int primary key, SumRecTbReadUncommitted int)
    
    insert into dbo.tbToUpdate(id, SumRecTbReadUncommitted)values (1,1)
    
    --vedo i dati e fine a qui ed è tutto congruente
    select * from dbo.tbToUpdate
    select * from dbo.tbReadUncommited
    
    02-Finestra_Dato_Fantasma
    
    -- FINESTRA SIMULAZIONE UTENTE APPLICAZIONE
    --  Qui si genera il dato fantasma
    --  Simulo un utente che sta lavorando all'applicazione e prova ad inserire 
    --  un record senza riuscirci per un errore qualsisai per cui ne viene eseguito il rollback
    begin tran
    
    insert into dbo.tbReadUncommited (id, valore)values (2,10)
    
    -- concedo 20 secondi per eseguire gli insert update  nell'altra finestra 03-Finestra_di_Insert_Update_Amministrativo
    WAITFOR DELAY '00:00:20'
    
    -- simulo un problema  qualsiasi che porta al rollback del dato inserito
    rollback
    
    03-Finestra_di_Insert_Update_Amministrativo
    
    /* 
    FINESTRA DI INSERT/UPDATE AMMINISTRATIVO 
    in cui un amministratore (chi ha aperto il thread per capirci) 
    vuole eseguire gli update/insert  correttivi
    */
    
    -- QUESTA ISTRUZIONE permette la lettura di enventuali  DATI FANTASMA,
    -- ovvero dati inseriti/aggiornati ma di cui verrà eseguito il rollback per un motivo qualsiasi
    set transaction isolation level read uncommitted
    
    begin tran
    
    update dbo.tbToUpdate 
    set SumRecTbReadUncommitted=(select sum (Valore) from  dbo.tbReadUncommited )
    
    commit
    
Devi accedere o registrarti per scrivere nel forum
11 risposte