2010-11-16 20 views
15

Sto tentando di scrivere in un file di registro all'interno di una transazione in modo che il registro sopravviva anche se la transazione viene annullata.Registrazione TSQL all'interno della transazione

codice --start

cominciano tran

inserire [qualcosa] in dbo.logtable

[[codice principale qui]]

rollback

commettere

- codice di fine

Si può dire basta fare il log prima che la transazione abbia inizio, ma non è così facile perché la transazione inizia prima che questo S-Proc venga eseguito (ad es. il codice fa parte di una transazione più grande)

Quindi, in breve, c'è un modo per scrivere un'istruzione speciale all'interno di una transazione che non fa parte della transazione. Spero che la mia domanda abbia un senso.

+0

Si prega di dare un'occhiata a http://stackoverflow.com/questions/3725356/suppress-transaction-in-stored-procedure –

risposta

12

Utilizzare una variabile di tabella (@temp) per contenere le informazioni del registro. Le variabili di tabella sopravvivono a un rollback della transazione.

Vedere this article.

+0

Proprio quello che stavo per suggerire. L'ho usato con successo molte volte. – HLGEM

+0

Il problema con questo è se qualcos'altro accade come un timeout di connessione o un timeout di esecuzione, rimarrai senza log. – Talon

2

Faccio questo in due modi, a seconda delle mie esigenze in quel momento. Entrambi implicano l'uso di una variabile, che conserva il valore dopo un rollback.

1) Creare un valore DECLARE @Log varchar(max) e utilizzare questo: @SET @ Log = ISNULL (@ Log + ';', '') + 'Le nuove informazioni del registro qui' . Keep appending to this as you go through the transaction. I'll insert this into the log after the commit or the rollback as necessary. I'll usually only insert the @Log value into the real log table when there is an error (in the blocco CATCH`) o Se sto provando a eseguire il debug di un problema.

2) creare un DECLARE @LogTable table (RowID int identity(1,1) primary key, RowValue varchar(5000). Inserisco in questo mentre procedi con la tua transazione. Mi piace usare la clausola OUTPUT per inserire gli ID effettivi (e altre colonne con messaggi, come "ELIMINARE l'articolo 1234") delle righe utilizzate nella transazione in questa tabella con. Inserirò questa tabella nella tabella di registro effettiva dopo il commit o il rollback secondo necessità.

+0

Entrambi sono buoni tranne che non ho un facile accesso alla parte della transazione. Fondamentalmente sto provando a eseguire il debug di un programma scritto in C#. – Arvid

+1

(finiamo questo :-) Il codice C# avvia una transazione, quindi chiama un s-proc e alla fine impegna o esegue il rollback della transazione. Ho solo un facile accesso a s-proc e speravo di poter fare un po 'di codice di debug che sarebbe sopravvissuto a un rollback – Arvid

+0

si potrebbe provare a usare [xp_cmdshell (Transact-SQL)] (http://msdn.microsoft.com /en-us/library/ms175046.aspx) (ma che potrebbe essere disattivato come rischio per la sicurezza) per includerli nella procedura: 'EXEC xp_cmdshell echo 'il tuo messaggio qui' >> log.txt' per scrivere in un file . si potrebbe anche provare a utilizzare un parametro di output @ErrorInfo varchar (max) 'dove si passano le informazioni sull'errore al programma C# in modo che possa registrarlo. –

1

Se la transazione padre ripristina i dati di registrazione verrà eseguito il rollback - Il server SQL non supporta le transazioni nidificate appropriate. Una possibilità è quella di utilizzare una procedura memorizzata CLR per eseguire la registrazione. Questo può aprire la propria connessione al database all'esterno della transazione e inserire e confermare i dati del registro.

+0

L'utilizzo della procedura di registrazione CLR è una delle migliori soluzioni. Se solo fosse possibile in qualche modo ottenere automaticamente i valori effettivi dei parametri con cui è stato chiamato lo sproc, possiamo sempre sognare. –

7

Vedere Logging messages during a transaction per una soluzione alternativa basata su sp_trace_generateevent che non richiede una variabile @table dell'ambito (che non è sempre possibile) o quando i limiti della transazione sono fuori dal controllo.

+0

Sembra che funzioni. Grazie a tutti per le risposte rapide. – Arvid

0

Se si desidera emulare il comportamento delle transazioni nidificato è possibile utilizzare le transazioni denominate:

begin transaction a 

create table #a (i int) 

select * from #a 
save transaction b 

create table #b (i int) 
select * from #a 
select * from #b 

rollback transaction b 

select * from #a 
rollback transaction a 

In SQL Server se si vuole un ‘sub-operazione’ si dovrebbe usare save transaction xxxx che funziona come un posto di blocco oracolo.

+3

Questa risposta non risponde affatto alla domanda. L'OP non si sta interrogando sulla sub-transazione, al contrario. Vuole che alcune operazioni vengano escluse dal contesto della transazione e che vengano immediatamente eseguite nel database. – Tipx

+0

la mia risposta è stata al commento sopra di esso - e penso che abbia risposto in modo abbastanza sintetico –

Problemi correlati