Любая операция внутри транзакции, которая откатывается, также откатывается. Невыполнение этого требования нарушит атомарность транзакции. Учитывая, что проверяемая вами деятельность откатывается, весьма вероятно, что вы все равно действительно хотите отменить аудит.
Тем не менее, существуют законные случаи, когда необходимо записывать операции вне области текущей транзакции, например, в определенных случаях отладки. Есть известные обходные пути, например, использование уведомлений о событиях для настраиваемого пользователем класса событий , затем использование sp_trace_generateevent
, чтобы вызвать уведомление о событии активированная процедура для запуска и записи аудита. Поскольку события профилировщика генерируются вне области транзакции, запись аудита не откатывается.
:setvar dbname testdb
:on error exit
set nocount on;
use master;
if exists (
select * from sys.server_event_notifications
where name = N'audit')
begin
drop event notification audit on server;
end
go
if db_id('$(dbname)') is not null
begin
alter database [$(dbname)] set single_user with rollback immediate;
drop database [$(dbname)];
end
go
create database [$(dbname)];
go
alter authorization on database::[$(dbname)] to [sa];
go
use [$(dbname)];
go
create queue audit;
create service audit on queue audit (
[http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]);
go
create table audit_table (
Time datetime not null,
TextData nvarchar(256) not null);
go
create procedure usp_audit
as
begin
declare @h uniqueidentifier, @mt sysname, @mb varbinary(max), @mx xml;
begin transaction;
receive top(1) @h = conversation_handle,
@mt = message_type_name,
@mb = message_body
from audit;
if (@mt = N'http://schemas.microsoft.com/SQL/Notifications/EventNotification')
begin
select @mx = cast(@mb as xml);
insert into audit_table (Time, TextData)
values (
@mx.value(N'(/EVENT_INSTANCE/PostTime)[1]', N'datetime'),
@mx.value(N'(/EVENT_INSTANCE/TextData)[1]', N'nvarchar(256)'));
end
else if (@mt = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
or @mt = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
begin
end conversation @h;
end
commit
end
go
alter queue audit
with activation (
status = on,
procedure_name = usp_audit,
max_queue_readers = 1,
execute as owner);
go
create event notification audit
on server for USERCONFIGURABLE_0
to service N'audit', N'current database';
go
begin transaction;
exec sp_trace_generateevent 82, N'this was inserted from a rolled back';
rollback
go
waitfor delay '00:00:05';
select * from audit_table;
go