一個事務中的任何操作是回滾回滾以及。不這樣做會破壞事務的原子性。鑑於您正在審計的活動正在回滾,很可能您確實希望無論如何都要回滾審計。
儘管如此,也有合法的情況下,當一個人需要有記錄當前事務,如某些調試案範圍以外的業務。有已知的解決方法,如使用event notifications爲user configurable事件類,然後使用sp_trace_generateevent
導致事件通知activated procedure運行並記錄審計。由於事件探查器事件是在事務作用域之外生成的,因此審覈記錄不會回滾。
: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
對不起,我的VB.net代碼。我錯過了'tx.Complete()'語句。但是,它永遠不會去那條線。因爲我總是在'cmd.ExecuteNonQuery()'方法後拋出異常。我想要的是回滾插入MY_TABLE中的記錄,但是** NOT **回滾插入AUDIT_TABLE中的記錄。 – 2011-03-04 00:39:01