1. Trang chủ
  2. » Công Nghệ Thông Tin

Hướng dẫn học Microsoft SQL Server 2008 part 127 ppt

10 99 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 10
Dung lượng 1,16 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Technology Introduced Events Tracked Data Available PerformanceDML Triggers — fires T-SQL code on table events Beginning of time Instead Of or After Insert, Update, Delete, Merge Inserte

Trang 1

Technology Introduced Events Tracked Data Available Performance

DML Triggers — fires T-SQL

code on table events

Beginning

of time

Instead Of or After Insert, Update, Delete, Merge

Inserted and deleted tables, all columns, all changes with user context

Synchronous within transaction; depending on width of table and amount of code, may have

a significant impact PerfMon/SysMon — Windows

utilities

Beginning

of time

Listens for hundreds of Windows/SQL Server events

Counters for nearly any event, no actual data

Virtually no impact

SQL Trace and Profiler — SQL

Server internal monitoring and UI

6.5 Monitors 179 SQL

Server internal events

Event data, no actual data

Profiler may have an impact, trace alone has little impact Wait States — tracks system

waits

7 Every time a process

waits for a resource

Aggregate count of waits

by wait type

No impact C2 Auditing — combines SQL

Trace and security settings for

compliance

2000 All security events All security-related data Minor impact

Common Criteria

Compliance — combines SQL

Trace and security settings for

compliance

2005 All security events All security-related data Minor impact

DMVs — dynamic management

views, catalog views

metadata and current status

No impact

Management Studio

Reports — easy way to view

DMV data

DMVs

Some impact depending on report

Performance Dashboard —

downloadable add-on with extra

reports

DMVs

Some impact depending on report

DDL Triggers — responds to

server and database DDL events

2005 All server and database

DDL events and logins

EventDate()

provides all info in XML format

Rarely called, so no real impact

Change Tracking —

synchronously records which

rows have been updated

2008 Row inserts, updates,

and deletes

PK with net change, columns changed, very limited user context

Little impact

Change Data Capture —

asynchronously reads T-Log and

records data changes

2008 Insert, Update, Delete,

Merge

All or net data changed, all column values, no user context

Reads from the log, so no impact during the transaction, but impact of the overall work Extended Events — lightweight

windows monitoring technology

2008 Nearly any server or

database event, similar

to SQL Trace

Event detail – similar to SQL Trace/Profiler

Very lightweight

SQL Auditing — SQL Server

interface for extended events

2008 Any extended event Detail dependent on

extended events

Very lightweight Management Data

Warehouse — collects

performance data

2008 Nearly continuous

recording of performance data

Aggregate historical performance data

Lightweight, but requires server

to collect data Policy-Based Management —

enforces and reports on

2008 Any defined

configuration policy

Can view health level of any object

No impact

Trang 2

Data Audit Triggers

IN THIS CHAPTER

Creating a robust data-audit trail

Rolling back changes Undeleting rows Thinking through auditing complications

My consulting firm once developed a legal compliance/best-practices

document-management system for a Fortune 100 company whose law

firm was populating the database with regulatory laws The law firm fell

behind on its schedule and claimed that it was unable to enter data for two weeks

because of software problems When a list of the more than 70,000 column-level

data changes made during those two weeks was provided from the data-audit

trail, the claim vanished

Data auditing is just a plain good idea

The section ‘‘Data Architecture’’ in Chapter 2 lists data auditing as a key

contribu-tor toward the security and integrity database objectives

Although Microsoft has added several auditing technologies, there’s still a place

for the old trigger/audit table solution It’s still the best way to build a complete

audit trail of every value change ever made to a row since the inception of

the database

A trigger based data-audit trail can provide very detailed history of the data,

including the following:

■ All data changes to a row since it was inserted

■ All data changes made by a specific user last week

■ All data changes from a certain workstation during lunch

■ All data changes made from an application other than the standard

front-end application

I’ve seen published methods of auditing data that add a few columns to the table,

or duplicate the table, to store the last change Neither of these methods is

worth-while A partial audit, or a last-value audit, is of no real value A robust audit trail

should track every change, from every table, in a generic audit table

Trang 3

Audit triggers that write every DML change to a generic audit table come in two basic flavors — fixed

and dynamic:

■ Fixed audit triggers: These are custom written for each table and include hard-coded code for each column There are two problems inherent with fixed audit triggers First, they are a pain to write: tedious, back-breaking, repetitive, time intensive, and error prone code

Second, the only task worse than coding a fixed audit trigger is maintaining it The audit triggers must be kept in perfect sync with everyALTER TABLE; otherwise, either the trigger generates an error, or the data audit trail is incomplete

■ Dynamic audit triggers: These investigate the metadata and either pass the data to the CLR

or use dynamic SQL to insert into the audit table There are a couple dynamic audit trigger

solutions on the Internet, and I published a dynamic SQL audit trigger in the SQL Server 2000

Bible These solutions are easy to implement but perform as well as a slug on a lazy day Plus,

the use of dynamic SQL requires the end-users to have more privileges in the database than is typically desired in most database applications

AutoAudit

The hybrid solution I’m proposing in this chapter is to dynamically code-gen perfect fixed audit trail

triggers using the techniques covered in Chapter 29, ‘‘Dynamic SQL and Code Generation.’’

The result is the best performance possible from a trigger, but no manual coding When the schema

changes, just rerun the code-gen procedure to recreate the audit trigger

As I’m writing, version 1.09a of AutoAudit is available on www.codeplex.com/AutoAudit.

It’s a work in progress, so check for updates.

Besides recording every column value change to an audit table, I like to record some generic audit data

right in the row:

■ Createdcolumn to record the date the row was inserted

■ Modifiedcolumn to timestamp the last update

■ Versioncolumn to count the number of times the row has been updated AutoAudit adds these three columns to any table, and code-gens the trigger code to keep themodified

andversioncolumns up-to-date

This version is limited to tables with single-column primary keys (That’s not likely to change anytime

soon, because modifying the audit table on the fly to handle composite primary keys adds too much

complexity and only a few have requested the feature.) It’s written to be compatible with SQL Server

2005 and SQL Server 2008

Installing AutoAudit

The first time the AutoAudit script is run in a database it creates thedbo.Audittable and four stored

procedures:

Trang 4

■ dbo.pAutoAudit: Code-gens the changes required for a single table

■ dbo.pAutoAuditAll: Executes AutoAudit on every table in the database

■ dbo.pAutoAuditDrop: Backs out the changes made by AutoAudit for a single table

■ dbo.pAutoAuditDropAll: Backs out the changes made by AutoAudit for every table in the

database

The audit table

TheAudittable’s purpose is to provide a single location in which to record data changes for the

database The following audit-trail table can store all non-BLOB changes to any table TheOperation

column stores anI,U, orD, depending on the DML statement This is the table created by executing

the AutoAudit script:

CREATE TABLE dbo.Audit (

AuditID BIGINT NOT NULL IDENTITY PRIMARY KEY CLUSTERED,

AuditDate DATETIME NOT NULL,

HostName sysname NOT NULL,

SysUser VARCHAR(50) NOT NULL,

Application VARCHAR(50) NOT NULL,

TableName SYSNAME NOT NULL,

Operation CHAR(1) NOT NULL, i,u,d

PrimaryKey INT NOT NULL, edit to suite

RowDescription VARCHAR(50) NULL, Optional

SecondaryRow VARCHAR(50) NULL, Optional

ColumnName SYSNAME NULL, required for i,u not for D

OldValue VARCHAR(50) NULL, edit to suite - varchar(MAX)?

NewValue VARCHAR(50) NULL

Version INT NULL

);

ThePrimaryKeycolumn stores the pointer to the row that was modified, and theRowDescription

column records a readable description of the row These two columns enable the audit trail to be joined

with the original table or viewed directly ThePrimaryKeycolumn is important because it can quickly

find all changes to a single row regardless of how the description has changed over time

Running AutoAudit

Once the AutoAudit script is run in the current database,pAutoAuditmay be executed for any table

The parameters are self-explanatory:

EXEC pAutoAudit @Schema, @Table;

The stored procedure makes several changes to the table:

1 Adds thecreated,modified, andversioncolumns to the table

2 Code-gens and creates the_modifiedupdate trigger, which updates themodifiedand

rowversioncolumns

Trang 5

3 Code-gens and creates the_updatetrigger, which writes any updated column values to the audittable

4 Code-gens and creates the_deletetrigger, which writes any deleted column values to the audittable

The stored procedure then creates two new objects in the database:

5 Code-gens and creates the_deletedview, which reassembles the deleted rows from the audittable

6 Code-gens and creates the_RowHistoryuser-defined function, which presents a historical view of the data for any row

The following code executespAutoAuditin theAdventureWorks2008database on the

Departmenttable:

EXEC pAutoAudit ‘HumanResources’, ‘Department’

ExecutingpAutoAuditAllwill runpAutoAuditagainst every table in the current database

_Modified trigger

The generatedProduct_ Modifiedtrigger isn’t very complicated The trigger simply updates the

modifiedcolumn to the current date time and increments therowversioncolumn As with any

trigger, joining theinsertedtable with the base table limits the rows affected to those rows being

updated:

CREATE TRIGGER [HumanResources].[Department_Modified] ON [HumanResources].[Department]

AFTER Update NOT FOR REPLICATION AS SET NoCount On

generated by AutoAudit on Apr 28 2009 3:38PM created by Paul Nielsen

www.SQLServerBible.com Begin Try

If Trigger_NestLevel (object_ID(N‘[HumanResources].[Department_Modified]’)) > 1 Return;

If (Update(Created) or Update(Modified)) AND Trigger_NestLevel() = 1 Begin; Raiserror(‘Update failed.’, 16, 1); Rollback; Return; End;

Update the Modified date UPDATE [HumanResources].[Department]

SET Modified = getdate(), [Version] = [Department].[Version] + 1 FROM [HumanResources].[Department]

JOIN Inserted

ON [Department].[DepartmentID] = Inserted.[DepartmentID] End Try Begin Catch

Raiserror(‘error in [HumanResources].[Department_modified] trigger’,

Trang 6

16, 1 ) with log

End Catch

GO

Auditing changes

The real workhorse of AutoAudit is the_Updatetrigger, which writes every update, column by

column, to theaudittable The trigger is a bit repetitive, but here’s a sample of the code it creates for

each column (slightly formatted for readability):

IF UPDATE([Name])

INSERT dbo.Audit

(AuditDate, SysUser, Application, HostName, TableName,

Operation, PrimaryKey, RowDescription, SecondaryRow,

ColumnName, OldValue, NewValue, RowVersion)

SELECT @AuditTime, suser_sname(), APP_NAME(), Host_Name(),

‘HumanResources.Department’, ‘u’, Convert(VARCHAR(50),

Inserted.[DepartmentID]),

NULL, Row Description (e.g Order Number)

NULL, Secondary Row Value

(e.g Order Number for an Order Detail Line)

‘[Name]’,

Convert(VARCHAR(50), Deleted.[Name]),

Convert(VARCHAR(50), Inserted.[Name]),

DELETED.Rowversion + 1

FROM Inserted

JOIN Deleted

ON Inserted.[DepartmentID] = Deleted.[DepartmentID]

AND isnull(Inserted.[Name],‘’) <> isnull(Deleted.[Name],‘’) Here’s how this works TheINSERTstatement joins theInsertedandDeletedtables on the primary

key to correctly handle multiple-row inserts and updates The join is also restricted with anot-equals

<>join condition so that when a multiple-row update only affects some of the rows for a given column,

only those rows that are actually changed are recorded to the audit trail

The_Inserttrigger audits all inserts In AutoAudit version 1.09b, inserts are minimally logged to save

space The only row written to theAudittable is the insert event with the primary key value The idea

is that between the base table, the insert event, and the fully audited updates, the complete history can

be reconstructed A popular request is the verbose insert, which would audit every value on insert — I’ll

probably add that to the next version

With AutoAudit’s code-generated ‘‘fixed audit trigger’’ installed, the following batch exercises it by

insert-ing and updatinsert-ing work order data:

INSERT Production.WorkOrder

(ProductID, OrderQty, ScrappedQty,

StartDate, EndDate, DueDate, ScrapReasonID)

VALUES (757, 25, 3,

‘2008-9-20’, ‘2008-9-23’, ‘2008-9-24’, 2)

Trang 7

UPDATE Production.WorkOrder SET DueDate = ‘2008-10-12’

WHERE WorkOrderID = 72592 With these two changes made, AutoAudit recorded these audits:

SELECT AuditDate, SysUser, Operation, PrimaryKey as Key, ColumnName, OldValue as Old, NewValue as New, Version

FROM dbo.Audit Result:

AuditDate SysUser Op Key ColumnName Old New Version - - - - - - -2009-04-28 20:10:50.567 Maui\Pn i 72592 [WorkOrderID] NULL 72592 1

2009-04-28 20:10:53.137 Maui\Pn u 72592 [ScrappedQty] 3 5 2 The trigger is the right place to implement an audit trail because it will catch all the changes, even those

made directly to the table with DML commands

Viewing and undeleting deleted rows

The_Deletetrigger writes all the final values for every column to theaudittable From this

infor-mation, the final state of the row can be easily recreated using a case expression-style crosstab query like

this one for theAdventureWorks2008products table (abbreviated for space):

SELECT Max(Case ColumnName WHEN ‘[ProductID]’ THEN OldValue ELSE ‘’ END) AS [ProductID], Max(Case ColumnName

WHEN ‘[Name]’ THEN OldValue ELSE ‘’ END) AS [Name], Max(Case ColumnName WHEN ‘[ProductNumber]’ THEN OldValue ELSE ‘’ END) AS [ProductNumber],

Max(Case ColumnName WHEN ‘[ModifiedDate]’ THEN OldValue ELSE ‘’ END) AS [ModifiedDate], Max(Case ColumnName

WHEN ‘[Created]’ THEN OldValue ELSE ‘’ END) AS [Created], Max(Case ColumnName

WHEN ‘[Modified]’ THEN OldValue ELSE ‘’ END) AS [Modified], Max(Case ColumnName

WHEN ‘[RowVersion]’ THEN OldValue ELSE ‘’ END) AS [RowVersion],

Trang 8

MAX(AuditDate) AS ‘Deleted’

FROM Audit

Where TableName = ‘SalesLT.Product’ AND Operation = ‘d’

GROUP BY PrimaryKey;

For every table audited by AutoAudit, it creates a view, namedvtablename_Deleted, that contains

the code-genned crosstab query Selecting from this view displays all the rows deleted from the table

To undelete rows, it’s trivial toinsert .selectfrom the_deletedview

Viewing row history

A feature I’ve recently added and am still enhancing is the row history user-defined function Its purpose

is to provide a visual history The function is code-genned when AutoAudit is applied to a table After

four updates to theDB Auditrow in theHumanResources.Departmenttable, the_RowHistory()

function returns the following story:

SELECT AuditDate, Version AS Ver, Name, GroupName

FROM HumanResources.Department_RowHistory(22)

Result:

- -

-2009-04-29 10:46:23 1 DB Audit Compliance Dept

2009-04-29 10:46:52 2 Data Audit Compliance Dept

2009-04-29 10:47:13 3 Data Auditing Compliance Dept

2009-04-29 10:47:26 4 Data Auditing Compliance and Audit Dept

2009-04-29 10:48:04 5 Data Forensics Data Audit

Note that the_RowHistory()function requires the primary key as a parameter To return multiple

histories, use theCROSS APPLYcommand

Backing out AutoAudit

AutoAudit makes several changes to the database schema, modifying tables and creating objects It

would be irresponsible to not provide an automated way to roll back these changes The following

command removes all changes made bypAutoAudit, with one key exception: It does not drop the

audittable, so any saved audit values are retained:

dbo.pAutoAuditDrop @Schema, @Table

Auditing Complications

While AutoAudit provides a rather complete audit trail solution, there are other factors that you should

consider when implementing it, modifying it, or creating your own custom solution

Trang 9

Best Practice

Develop the entire database and prove that the data schema is correct prior to implementing a data-audit

trail Changes to the data schema are more complex once audit-trail triggers are in place

Auditing related data

The most significant complication involves auditing related data such as secondary rows For example,

a change to anOrderDetailrow is actually a change to the order A user will want to see the data

history of the order and all changes to any of the data related to the order Therefore, a change to the

OrderDetailtable should be recorded as a change to the[Order]table, and the line number of

the order detail item that was changed is recorded in theSecondaryRowcolumn

Recording foreign key changes is another difficult aspect of a full audit trail A user does not want to

see the new GUID or identity value for a foreign-key update If the order-ship-method foreign key is

changed from ‘‘Slow Boat’’ to ‘‘Speedy Express,’’ the audit-trail viewing procedure might want to look up

the meaningful value and display that instead of the surrogate key value

Auditing select statements

Data-audit triggers are limited to auditingINSERT,UPDATE, andDELETEDML statements To audit

data reads, implement the read audit in theFETCHstored procedure Use SQL Server security to limit

access to the table so that all reads must go through a stored procedure or a function

In my software product I record everyobjectfetchoperation with theobjectID,username, and

datetimein a separate table This table serves as a select audit and feeds the user’s recently viewed

objects feature

Data auditing and security

Another concern for those creating a full data-audit history is the security of the data-audit trail

Any-one who has read rights to the audit table will be able to effectively see all the data from every audited

table If users will be able to see the data history for a given row, use a stored procedure to fetch the

audit data so that security can be preserved

Data auditing and performance

A full data-audit trail will add some level of overhead to the system A single row insert to a

20-column-wide table will add 20 inserts to the audit table To reduce the performance impact of the audit trail, do

the following:

■ Limit the indexes on the audit table

■ Locate the audit table on its own filegroup and disk subsystem A separate filegroup will make backups easier as well

Trang 10

■ Consider archiving older audits and then using distributed partitioned views to see all the

audit data

■ Edit the fixed audit trigger to limit the auditing to those columns that require such a high level

of data integrity

One question when creating an audit trail is whether or not to write the insert DML values to the audit

trail Including the inserts completes the audit trail, and the rows may theoretically be completely

recre-ated from the audit trail alone The problem, of course, with writing inserts is that the audit trail grows

larger than the original base tables

Most OLTP databases see significantly more inserts than updates Most rows are inserted and never

updated Therefore, if the original tables are used to store the original data, and the audit trail records

only insert events and changes, then theaudittable is significantly smaller than if every insert were

fully audited This improves performance by eliminating the audit during inserts and reduces the size of

the audit table

AutoAudit only records update values, but the commented out code to code-gen an insert audit

trigger is in the AutoAudit stored procedure

Summary

With all the new compliance regulations and requirements, auditing is more important than ever But

auditing is a pain I’ve wasted way too many hours keeping a fixed audit trail in sync with schema

changes, and the best dynamic audit triggers are slow

I’ve created AutoAudit to help you solve some of your auditing problems If after using it you have any

suggestions, e-mail them to me, or add a request in CodePlex and vote for your idea

Key points from this chapter include the following:

■ A single audit table is easier to query for changes across the whole database than an individual

audit-table-per-base-table approach

■ AutoAudit will code-gen triggers, views, and user-defined functions for your auditing solution

■ Deleted rows can be viewed or undeleted using thevtable_deletedview

■ Row history can be viewed using the well-named_RowHistoryuser-defined function

■ AutoAudit requires a single-column primary key

■ Suggest improvements and vote for enhancements onwww.CodePlex.com/AutoAudit

The next chapter continues the thread of auditing with triggers, but it moves from auditing data to

auditing the schema

Ngày đăng: 04/07/2014, 09:20

TỪ KHÓA LIÊN QUAN