[SQL 2008] Transazioni autonome
SQL Server non ha, nativamente, il supporto alle transazioni autonome come ha, ad esempio, Oracle.
Prima di tutto, di cosa stiamo parlando?
Si definisce transazione autonoma una transazione che, innestata all'interno di un'altra, non ne subisce lo stato.
Cerco di spiegarmi con un esempio.
- apro una transazione
- provoco un errore esplicito (ad esempio una divisione per zero)
- apro una seconda transazione
- chiudo la seconda transazione
- chiudo la (prima) transazione
Fino a ieri (SQL 2005) la transazione interna era comunque influenzata dalla prima, quindi se fosse andata in rollback la prima sarebbe andata in rollback anche la seconda e... addio log della mia applicazione...
Oggi SQL Server 2008 introduce una nuova opzione server: remote proc transaction promotion (vedi msdn) che ci consente di isolare la tranazione, di renderla autonoma.
Vediamo un esempio pratico:
Use master
go
EXEC sp_addlinkedserver @server = N'myServer',@srvproduct = N' ',@provider = N'SQLNCLI', @datasrc = @@SERVERNAME
EXEC sp_serveroption myServer,N'remote proc transaction promotion','FALSE'
EXEC sp_serveroption myServer,N'RPC OUT','TRUE'
go
-- creo un database Ugiss
IF EXISTS (SELECT name FROM sys.databases WHERE name = N'Ugiss')
DROP DATABASE Ugiss
GO
CREATE DATABASE Ugiss
GO
Use Ugiss
go
-- creo la tabella di log
create table applicationLog
(
idRecord int primary key identity(1,1),
data datetime default(getdate()),
descrizione varchar(200)
)
go
-- stored procedure per insert log
create procedure up_insertApplicationLog
(
@descrizione varchar(200)
)
AS
set nocount on
insert applicationLog (descrizione) values (@descrizione)
set nocount off
go
/* start test transazione autonoma */
declare @errorCode int
begin tran appTran
select 1/0
select @errorCode = @@error
if (@errorCode <> 0)
begin
begin tran autTran
declare @str varchar(200)
set @str = 'Attenzione: errore ' + cast(@errorCode as varchar(10))
-- chiamo la procedura tramite linked server
exec myServer.Ugiss.dbo.up_insertApplicationLog @str
commit tran autTran
rollback tran appTran
end
if (@@TRANCOUNT > 0) commit tran appTran
go
-- vedo la tabella di log
select * from applicationLog
go
exec sp_dropserver 'myServer'
go
Il risultato che otterremo, nei messaggi, sarà proprio l'errore:
Msg 8134, Level 16, State 1, Line 6
Divide by zero error encountered.
Ma questa volta la nostra tabella di log sarà popolata!
