Auditing SQL Server 2005 Through Transaction Log
Jun 4, 2007
Hello,
We are maintaining an internal ASP.NET v2.0 website which is quite big and already in production. The underlying SQL Server 2005 database contains 350+ tables.
Recently, we have been asked to implement a new feature which seems functionally quite simple. We have to track every single data modification, which includes insertions, deletions and modifications. This information should be presented to power users in the form of readable strings right in an admin section of our website.
Our team of architects is working on a way to make it possible without putting the SQL Server to a crawl. One thing is for sure, SQL Server 2005 already does the job through its transaction log. It should be a good idea to use it directly instead of managing our own log based on triggers. Why put more pressure on the server to write data that is already logged by the database engine? We have heard that Microsoft's SQL Server team do not support this concept and are wondering why...
It's quite easy to find queries on the web that output very useful information such as date of transactions and what they have done. Although, the data involved in those transactions seems to be stored in a binary field which can be retrived using this query: SELECT "log record" FROM ::fn_dblog(null,null)
3rd parties such as Apex SQL are already doing a great job at decrypting it for us. This is very useful but not efficient since those tools do a very generic job. We would like to optimize it for our needs. All we need to know is who made the modifications, when, in which tables and what are the new values.
We believe that we would have to decrypt the "log record" field from the ::fn_dblog(null, null) table. Is there any way to get basic documentation about how to do it?
Thanks!
Marc Lacoursiere
RooSoft Computing
View 9 Replies
May 5, 2008
Below is a script I found that will help me turn on C2 auditing. The problem is that I am generating trace files that take up way too much space.
I need to know what column id and event id, so I am only turning on "failed login" and nothing else.
exec sp_trace_setevent @TraceID, x, x, @on
Code Snippet
CREATE PROC AuditTrcProc AS
-- Create a Queue
declare @rc int
declare @TraceID int
declare @maxfilesize bigint
set @maxfilesize = 1
-- Please replace the test InsertFileNameHere with an appropriate
-- filename prefixed by a path, eg.. c:MyFolderMyTrace. The .trc extention
-- will be appended to the filename automatically. If you are writing from
-- remote server to local crive, please use UNC path and make sure server has
-- write access to your network share
declare @cmd sysname
set @cmd = 'copy c: empsessiontrace.trc c: empsession' + cast(cast(rand() * 1000000 as int) as varchar)
print @cmd
exec master..xp_cmdshell @cmd
set @cmd = 'del c: empsessiontrace.trc'
print @cmd
exec master..xp_cmdshell @cmd
exec @rc = sp_trace_create @TraceID output, 2, N'c: empsessiontrace.trc', @maxfilesize, null
if (@rc != 0) goto error
-- Client side file and table cannot be scripted
-- set the events
declare @on bit
set @on = 1
exec sp_trace_setevent @TraceID, 10, 1, @on
exec sp_trace_setevent @TraceID, 10, 6, @on
exec sp_trace_setevent @TraceID, 10, 9, @on
exec sp_trace_setevent @TraceID, 10, 10, @on
exec sp_trace_setevent @TraceID, 10, 11, @on
exec sp_trace_setevent @TraceID, 10, 12, @on
exec sp_trace_setevent @TraceID, 10, 13, @on
exec sp_trace_setevent @TraceID, 10, 14, @on
exec sp_trace_setevent @TraceID, 10, 16, @on
exec sp_trace_setevent @TraceID, 10, 17, @on
exec sp_trace_setevent @TraceID, 10, 18, @on
exec sp_trace_setevent @TraceID, 12, 1, @on
exec sp_trace_setevent @TraceID, 12, 6, @on
exec sp_trace_setevent @TraceID, 12, 9, @on
exec sp_trace_setevent @TraceID, 12, 10, @on
exec sp_trace_setevent @TraceID, 12, 11, @on
exec sp_trace_setevent @TraceID, 12, 12, @on
exec sp_trace_setevent @TraceID, 12, 13, @on
exec sp_trace_setevent @TraceID, 12, 14, @on
exec sp_trace_setevent @TraceID, 12, 16, @on
exec sp_trace_setevent @TraceID, 12, 17, @on
exec sp_trace_setevent @TraceID, 12, 18, @on
exec sp_trace_setevent @TraceID, 14, 1, @on
exec sp_trace_setevent @TraceID, 14, 6, @on
exec sp_trace_setevent @TraceID, 14, 9, @on
exec sp_trace_setevent @TraceID, 14, 10, @on
exec sp_trace_setevent @TraceID, 14, 11, @on
exec sp_trace_setevent @TraceID, 14, 12, @on
exec sp_trace_setevent @TraceID, 14, 13, @on
exec sp_trace_setevent @TraceID, 14, 14, @on
exec sp_trace_setevent @TraceID, 14, 16, @on
exec sp_trace_setevent @TraceID, 14, 17, @on
exec sp_trace_setevent @TraceID, 14, 18, @on
exec sp_trace_setevent @TraceID, 15, 1, @on
exec sp_trace_setevent @TraceID, 15, 6, @on
exec sp_trace_setevent @TraceID, 15, 9, @on
exec sp_trace_setevent @TraceID, 15, 10, @on
exec sp_trace_setevent @TraceID, 15, 11, @on
exec sp_trace_setevent @TraceID, 15, 12, @on
exec sp_trace_setevent @TraceID, 15, 13, @on
exec sp_trace_setevent @TraceID, 15, 14, @on
exec sp_trace_setevent @TraceID, 15, 16, @on
exec sp_trace_setevent @TraceID, 15, 17, @on
exec sp_trace_setevent @TraceID, 15, 18, @on
exec sp_trace_setevent @TraceID, 17, 1, @on
exec sp_trace_setevent @TraceID, 17, 6, @on
exec sp_trace_setevent @TraceID, 17, 9, @on
exec sp_trace_setevent @TraceID, 17, 10, @on
exec sp_trace_setevent @TraceID, 17, 11, @on
exec sp_trace_setevent @TraceID, 17, 12, @on
exec sp_trace_setevent @TraceID, 17, 13, @on
exec sp_trace_setevent @TraceID, 17, 14, @on
exec sp_trace_setevent @TraceID, 17, 16, @on
exec sp_trace_setevent @TraceID, 17, 17, @on
exec sp_trace_setevent @TraceID, 17, 18, @on
-- Set the Filters
declare @intfilter int
declare @bigintfilter bigint
exec sp_trace_setfilter @TraceID, 10, 0, 7, N'SQL Profiler'
-- Set the trace status to start
exec sp_trace_setstatus @TraceID, 1
-- display trace id for future references
select TraceID=@TraceID
goto finish
error:
select ErrorCode=@rc
return @rc
finish:
return @TraceID
View 6 Replies
View Related
Mar 4, 2008
Hi all,I am trying to setup a VB.Net development environment on my desktop for one of the application which was already in the production for couple of years (some unknown contractor(s) developed and maintained it so far). The application works fine on the web.Visual Studio 2005, .Net 2.0, SQL 2000, SQL Server 2005 were installed on my desktop. When I try to build the entire application/solution in the debug mode (i.e., with http://localhost/), build succeeds and I could get to the login.aspx. When I try to login, I am getting an error in the Visual Studio at the following code;connection = New SqlConnection(connectionString)
connection.Open()
saying "Communication with the underlying transaction manager has failed", "System.Transactions.TransactionManagerCommunicationException was unhandled by user code". And the web browser displays the following error "Error HRESULT E_FAIL has been returned from a call to a COM component". When I try to connect the SQL Server 2005 with the same ConnectionString attributes by going to Tools>Connect to Database, it works fine. But, through application connection.Open() giving above errors. I have set the MSDTC properties (i.e., under Component Services>MyComputer Properties>Security Configuration) as below:-Enabled Network DTC Access, Allow Remote Clients, Allow Remote Administration, Allow Inbound, Allow Outbound, No Authentication required - selected, Enabled XA Transactions...& DTC Logon Account is "NT AUTHORITYNetworkService".Please help.Thanks in advance,Chandra
View 3 Replies
View Related
Sep 1, 2005
It seems to me there are two common strategies for doing DB audit trails via a trigger:
1. On an update to a row, duplicate that row in another table with
identical rows, except for perhaps the extra columns which represent
change date and changed by. Eg. When there is an update to the Customer
table, record the changes in Customer_Audit.
2. On an update to a row, check which fields were updated. Then in a
common audit table record the table, row ID, field, previous value and
new value of the field.
I'm wondering about the pros and cons of each. More specifically, do
the pros and cons change if you are using an O/R mapper (I'm using
NHibernate.)
Some thoughts on method 1 . It seems nice for an O/R mapper, since you
could have, say, a CustomerAudit Object inherit from your Customer
object and just add the properties change date and changed by. A
problem with this is you're going to add a whole lot of objects - one
for each object which you want to audit. Another drawback is that it
could be difficult to generate a history for a particular property
which was updated. Let's say I want to see the history of changes to
the customer's status. I have to load a collection of CustomerAudit
objects (which could be costly). Then I have to iterate through them
and compare the status properties to generate a history of statuses.
This is a pretty labor instensive method if you compare it to method 2,
where the change is recorded by field, not row.
Some thoughts on method 2. It's nice since the changes are by field,
not row, which (as above) makes generating a history easy. On the other
hand, you can never have a snapshot of a particular object at a
particular point in time. Moreover, I'm not sure how foreign keys would
be handled elegantly. I record that customer.statusID changes from 3 to
6. I'd have to do a seperate join to the customerstatus table to get
meaning for 3 and 6 (which method 1 would do automatically).
Thoughts? Any preferred way to do this with an O/R mapper?
Thanks
View 1 Replies
View Related