Pregunta

Estoy usando SQL Express 2008 R2 Express Edition.

¿Es posible hacer escrituras dentro de un desencadenante independiente de la transacción de la declaración que hace que el gatillo se dispare?

Tengo desencadenantes trabajando para auditar simple en algunas tablas en mi DB. Tengo una tabla para mantener los datos de auditoría (busque aquí Para más detalles) funciona bien, excepto que no quiero que se desaparezcan los datos de auditoría cuando la transacción se remonta. Por lo tanto, quiero escribir datos de auditoría en la tabla de auditoría independientemente de la transacción de la declaración que hace que mi disparador de auditoría dispare.

¿Fue útil?

Solución

Una solución es agregar un servidor vinculado a su propio sever. En el servidor vinculado, deshabilite las transacciones. Cualquier llamada realizada al servidor vinculado ahora se ejecutará en su propia transacción.

Ejemplo de configuración:

-- Add linked server called LOCALHOST
USE [master]
IF  EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND srv.name = N'LOCALHOST')
    EXEC master.dbo.sp_dropserver @server=N'LOCALHOST', @droplogins='droplogins'

EXEC master.dbo.sp_addlinkedserver @server = N'LOCALHOST', @srvproduct=N'SQL Server'
-- Allow procedure calls
EXEC master.dbo.sp_serveroption @server=N'LOCALHOST', @optname=N'rpc out', @optvalue=N'true'
-- But do not allow the procedure calls to enlist in our transaction
EXEC master.dbo.sp_serveroption @server=N'LOCALHOST', @optname=N'remote proc transaction promotion', @optvalue=N'false'
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'LOCALHOST', @locallogin = NULL , @useself = N'true'

-- Create a test procedure
use TestDatabase
if exists (select * from sys.tables where name = 'Log')
    drop table log
if exists (select * from sys.procedures where name = 'WriteLog')
    drop procedure WriteLog
go
create table log (id int identity, message varchar(256))
go
create procedure WriteLog
as
insert Log (message) values ('Hello World!')
go

Código de prueba:

-- Insert through a direct call, and then through a linked server call
begin transaction
exec TestDatabase.dbo.WriteLog
exec [Localhost].TestDatabase.dbo.WriteLog
rollback transaction

select * from Log

los select Mostrará solo 1 fila. los rollback No ha deshecho los efectos de la llamada de servidor vinculado.

Si bien es un buen truco, esto probablemente no sea algo que quieras hacer dentro de un entorno de producción. Personalmente, solo permitiría modificaciones de datos a través de un procedimiento almacenado y agregaría registro en el procedimiento almacenado en sí, antes de iniciar una transacción (si la hay).

Otros consejos

Use Service Broker para desacoplar la transacción del registro de escritura.

Eso es, Empuje la información de cambio a la cola de corredor de servicio que algún oyente consumirá. Más código de muestra en esta respuesta dba.se

Licenciado bajo: CC-BY-SA con atribución
No afiliado a dba.stackexchange
scroll top