Tôi đã tạo một thử nghiệm đơn giản để dùng thử SQL Server Audit dựa trên các trình kích hoạt và các tùy chọn tiềm năng khác. Trong các thử nghiệm của tôi về việc chèn 1 triệu hàng vào bảng tôi đã nhận được 52, 67 và 159 giây cho đường cơ sở, Kiểm toán SQL và trình kích hoạt của tôi tương ứng:
Bây giờ điều này không đặc biệt khoa học nhưng có khả năng cung cấp cho bạn một cách so sánh các phương pháp. Hãy xem qua kịch bản, xem nó có thể được sử dụng cho bạn không:
USE master
GO
SET NOCOUNT ON
GO
IF EXISTS ( SELECT * FROM sys.databases WHERE name = 'testAuditDb' )
ALTER DATABASE testAuditDb SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
IF EXISTS ( SELECT * FROM sys.databases WHERE name = 'testAuditDb' )
DROP DATABASE testAuditDb
GO
CREATE DATABASE testAuditDb
ON PRIMARY
( NAME = N'testAuditDb', FILENAME = N's:\temp\testAuditDb.mdf', SIZE = 1GB, MAXSIZE = UNLIMITED, FILEGROWTH = 128MB )
LOG ON
( NAME = N'testAuditDb_log', FILENAME = N's:\temp\testAuditDb_log.ldf', SIZE = 100MB, MAXSIZE = 2048GB, FILEGROWTH = 128MB )
GO
ALTER DATABASE testAuditDb SET RECOVERY SIMPLE
GO
------------------------------------------------------------------------------------------------
-- Setup START
------------------------------------------------------------------------------------------------
USE testAuditDb
GO
CREATE SCHEMA auditSchema
-- Create a table
CREATE TABLE auditSchema.auditTable (
rowId INT IDENTITY PRIMARY KEY,
someData UNIQUEIDENTIFIER DEFAULT NEWID(),
dateAdded DATETIME DEFAULT GETDATE(),
addedBy VARCHAR(30) DEFAULT SUSER_NAME(),
ts ROWVERSION
)
GO
-- Setup END
------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------
-- Test 01 - Baseline START
-- Normal timing; no triggers or audits
------------------------------------------------------------------------------------------------
-- Add a million rows to the table and time it.
DECLARE @i INT = 0, @startTime DATETIME2, @endTime DATETIME2
SET @startTime = SYSDATETIME()
WHILE @i < 1000000
BEGIN
INSERT INTO auditSchema.auditTable DEFAULT VALUES
SET @i += 1
END
SET @endTime = SYSDATETIME()
SELECT DATEDIFF( second, @startTime, @endTime ) AS baseline
GO
-- Cleanup
TRUNCATE TABLE auditSchema.auditTable
GO
-- Test 01 - Baseline END
------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------
-- Test 02 - SQL Audit START
-- Try SQL Audit
------------------------------------------------------------------------------------------------
-- Create server audit in master database
USE master
GO
------------------------------------------------------------------------------------------------------------------------
-- The server audit is created with a WHERE clause that limits the server audit to only the auditTable table.
------------------------------------------------------------------------------------------------------------------------
CREATE SERVER AUDIT auditTableAccess TO FILE ( FILEPATH = 'S:\SQLAudit\' ) WHERE object_name = 'auditTable';
GO
ALTER SERVER AUDIT auditTableAccess WITH ( STATE = ON );
GO
-- Create the database audit specification in the testAuditDb database
USE testAuditDb;
GO
CREATE DATABASE AUDIT SPECIFICATION [dbAudit1]
FOR SERVER AUDIT auditTableAccess
ADD (
SELECT, INSERT, UPDATE ON SCHEMA::[auditSchema]
BY [public]
) WITH ( STATE = ON );
GO
-- Add a million rows to the table and time it.
DECLARE @i INT = 0, @startTime DATETIME2, @endTime DATETIME2
SET @startTime = SYSDATETIME()
WHILE @i < 1000000
BEGIN
INSERT INTO auditSchema.auditTable DEFAULT VALUES
SET @i += 1
END
SET @endTime = SYSDATETIME()
SELECT DATEDIFF( second, @startTime, @endTime ) AS sqlAudit
GO
-- Cleanup
TRUNCATE TABLE auditSchema.auditTable
GO
ALTER DATABASE AUDIT SPECIFICATION [dbAudit1] WITH ( STATE = Off );
DROP DATABASE AUDIT SPECIFICATION [dbAudit1]
GO
USE master
ALTER SERVER AUDIT auditTableAccess WITH ( STATE = OFF );
DROP SERVER AUDIT auditTableAccess
GO
/*
-- Inspect the audit output
IF OBJECT_ID('tempdb..#tmp') IS NOT NULL DROP TABLE #tmp
SELECT *
INTO #tmp
FROM fn_get_audit_file ( 'S:\SQLAudit\auditTableAccess_*.sqlaudit', DEFAULT, DEFAULT );
GO
SELECT statement, MIN(event_time), MAX(event_time), COUNT(*) AS records
FROM #tmp
GROUP BY statement
GO
*/
-- Test 02 - SQL Audit END
------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------
-- Test 03 - Triggers START
-- Trial INSERT/UPDATE trigger with log table
------------------------------------------------------------------------------------------------
USE testAuditDb
GO
CREATE TABLE dbo.auditLog
(
auditLogLog INT IDENTITY PRIMARY KEY,
schemaName SYSNAME NOT NULL,
tableName SYSNAME NOT NULL,
dateAdded DATETIME NOT NULL DEFAULT GETDATE(),
addedBy SYSNAME NOT NULL DEFAULT SUSER_NAME(),
auditXML XML
)
GO
-- Generic audit trigger
CREATE TRIGGER trg_dbo__triggerTest ON auditSchema.auditTable
FOR INSERT, UPDATE, DELETE
AS
BEGIN
IF @@rowcount = 0 RETURN
SET NOCOUNT ON
DECLARE @action VARCHAR(10)
IF EXISTS ( SELECT * FROM inserted )
AND EXISTS ( SELECT * FROM deleted )
SET @action = 'UPDATE'
ELSE IF EXISTS ( SELECT * FROM inserted )
SET @action = 'INSERT'
ELSE IF EXISTS ( SELECT * FROM deleted )
SET @action = 'DELETE'
INSERT INTO dbo.auditLog ( schemaName, tableName, auditXML )
SELECT OBJECT_SCHEMA_NAME( parent_id ) schemaName, OBJECT_NAME( parent_id ) tableName,
(
SELECT
@action "@action",
( SELECT 'inserted' source, * FROM inserted FOR XML RAW, TYPE ),
( SELECT 'deleted' source, * FROM deleted FOR XML RAW, TYPE )
FOR XML PATH('mergeOutput'), TYPE
) x
FROM sys.triggers
WHERE OBJECT_ID = @@procid
AND ( EXISTS ( SELECT * FROM inserted )
OR EXISTS ( SELECT * FROM deleted )
)
END
GO
-- Add a million rows to the table and time it.
DECLARE @i INT = 0, @startTime DATETIME2, @endTime DATETIME2
SET @startTime = SYSDATETIME()
WHILE @i < 1000000
BEGIN
INSERT INTO auditSchema.auditTable DEFAULT VALUES
SET @i += 1
END
SET @endTime = SYSDATETIME()
SELECT DATEDIFF( second, @startTime, @endTime ) AS triggers
GO
-- Cleanup
TRUNCATE TABLE auditSchema.auditTable
DROP TABLE dbo.auditLog
DROP TRIGGER auditSchema.trg_dbo__triggerTest
GO
-- Test 03 - Triggers END
------------------------------------------------------------------------------------------------
Mặc dù tùy chọn kích hoạt không hoạt động tốt ở đây, mã kích hoạt của tôi có thể được đơn giản hóa tùy thuộc vào những gì bạn muốn nắm bắt và nó cho phép bạn truy cập vào các giá trị cũ và mới theo định dạng khá hữu dụng mà SQL Audit không sử dụng được. Tôi đã sử dụng kỹ thuật này cho một bảng cấu hình hoạt động thấp hơn và nó hoạt động khá tốt. Tùy thuộc vào những gì bạn muốn chụp, bạn cũng có thể xem xét Thay đổi dữ liệu .
Hãy cho tôi biết làm thế nào bạn có được với các thử nghiệm của bạn. Chúc may mắn.