2009-12-22 4 views
5

Nella nostra applicazione, c'è un aggiornamento del database che viene eseguito solo dopo l'esecuzione di un conseguente aggiornamento (ovviamente utilizzando la stessa transazione, ovviamente). Tuttavia, abbiamo scoperto un flusso raro in cui l'utente esce dall'applicazione prima del secondo aggiornamento, causando il primo a essere scartato. Sto cercando un modo per riconoscere questo aggiornamento senza commit all'uscita.Indicare se una transazione ha aggiornamenti non salvati

Conosco problemi come questa chiamata per la riprogettazione, ma ciò non è possibile. A causa della rarità del flusso e della struttura dell'app, mi chiedo se c'è un modo per controllare la transazione stessa per gli aggiornamenti non vincolati.

La domanda è valida per Oracle e SQLServer. L'app è scritta in PowerBuilder, ma può essere estesa in vari modi (.NET, Win32 ecc.) Se questo è importante.

risposta

5

In Oracle è possibile chiamare DBMS_TRANSACTION.local_transaction_id. Ciò restituirà un identificatore univoco della transazione corrente o NULL se nessuna transazione è attiva.

Condividi e divertiti.

4

Questo potrebbe essere utile

@@TRANCOUNT (Transact-SQL)

Restituisce il numero di attivi transazioni per l'attuale collegamento .

+0

Ho pensato che fosse solo SQL Server? –

0

Per facilitare la risoluzione dei problemi del proprio scenario, si potrebbe prendere in considerazione l'uso di transazioni locali con nome esplicito, insieme all'utilizzo dell'opzione "WITH MARK". Ciò consente di registrare il nome di una transazione esplicita nel log delle transazioni, che è possibile ispezionare in una fase successiva per identificare la sequenza di eventi verificatisi.

See linea di SQL Server: Marked Transactions

1

In Oracle v'è una vista V$TRANSACTION che contiene una riga per ogni transazione senza commit. Non esiste alcun meccanismo per vedere la natura di quella transazione dall'esterno (a meno che non si abbia la strumentazione incorporata nel codice, ad esempio utilizzando DBMS_APPLICATION_INFO.SET_MODULE()). Tuttavia, la sessione corrente poteva vedere se è non legato lavoro come questo:

SQL> select t.status 
    2 from v$transaction t 
    3   join v$session s 
    4   on s.saddr = t.ses_addr 
    5 where s.sid = sys_context('userenv', 'sid') 
    6/

STATUS 
---------------- 
ACTIVE 

SQL> 

Se non ci sono transazioni non allora questa query restituirà NO_DATA_FOUND. Le visualizzazioni V $ non sono concesse agli utenti per impostazione predefinita, in quanto sono in realtà un thang DBA. Tuttavia, un utente con il privilegio appropriato può trasformare questa query in una vista e concedere l'accesso ai joes regolari.

Per una questione di interesse, cosa vorresti fare, comunque? Presumendo che l'unità di lavoro sia definita correttamente con due aggiornamenti, sicuramente sarebbe sbagliato commettere solo quella. Se tutto ciò che si vuole sapere è che questa interruzione anomala si è verificata, allora è necessaria una qualche forma di traccia o di registrazione.

modificare

Bob Jarvis proposes utilizzando DBMS_TRANSACTION.LOCAL_TRANSACTION_ID(). Questo è un suggerimento migliore di una vista artigianale. La visualizzazione V $ TRANSACTION può anche essere utilizzata per monitorare transazioni non vincolate da altre sessioni.

+0

Bene, i due aggiornamenti non sono in realtà una sola unità di lavoro. L'aggiornamento senza commit è in realtà una chiamata reinstradata a un server esterno, che invece di essere trasmessa viene archiviata nel DB. La nostra app ha un comportamento coerente per quanto riguarda l'impegno, ma l'aggiornamento proviene da una parte diversa dell'app. Una transazione separata avrebbe potuto essere appropriata, ma anche questo avrebbe richiesto molto lavoro. Quindi, dovrebbe essere ok per commettere l'unico aggiornamento non impegnato. – eran

0

In SQL Server, eseguire questo:

IF @@TRANCOUNT>0 BEGIN 
    ROLLBACK; 
END; 
2

Se siete su PB11.5 e si utilizza un oggetto di transazione personalizzato, è abbastanza facile da fare qualcosa che non è DBMS-dipendente. Nell'evento SQLPreview dell'oggetto transazione, è sufficiente attivare un valore booleano quando si passa da INSERT, UPDATE o DELETE, quindi disattivarlo quando passa COMMIT o ROLLBACK.

In realtà, non è difficile scambiare un oggetto di transazione personalizzato se si utilizza SQLCA: applicazione, proprietà, proprietà aggiuntive, tipi di variabili, SQLCA. Se si utilizzano molte connessioni di database separate con molte istruzioni "CREATE transaction" (la ricerca PB standard può trovare questo, o PBL Peeper può aiutarti a trovare questo con un numero variabile di spazi tra le parole), quindi l'implementazione sarà più difficile, ma non impossibile.

E, per motivi di completezza, creare un oggetto di transazione personalizzato, File/Nuovo/Oggetto PB/Classe standard/Transazione. Hai un normale oggetto utente in cui puoi definire le variabili di istanza (come il booleano che ho suggerito) e gli eventi di script (come l'evento SQLPreview che ho suggerito) e le funzioni (potresti voler creare un'interfaccia per questa funzionalità nascondere i dettagli nel caso in cui si desideri estenderlo in futuro). Si noti che SQLPreview non è disponibile sull'oggetto Transaction prima di 11.5. (Per quelli che pensano che suona familiare prima di 11.5, il DataWindow implementa uno SQLPreview.)

Buona fortuna,

Terry.

+0

Buono a sapersi. Grazie, Terry! – eran

+0

Non sto ottenendo il COMMIT o il ROLLBACK nell'anteprima SQL delle transazioni. PB 12.5, connessione ODBC. Questo mi deprime davvero perché ho creato una finestra simile a quella di SQL Spy che mostra tutto l'SQL che va al database e trasforma una grande barra di indicatori rossa se c'è una transazione senza commit. –