拡張イベントとSQL監査-パフォーマンスへの影響


8

UPDATE/INSERT非常にアクティビティの多い特定のテーブルのステートメントを監視するために、データベースに監査証跡のようなシステムをセットアップしたいと思います。私の目の前には、SQL Serverの組み込み監査システムを使用するか、拡張イベントを使用するという2つのオプションがあります。

SQL Server Auditは内部的に拡張イベントを使用するため、拡張イベントの代わりに直接監査を使用すると、ある種のオーバーヘッドがあると思います。

どのシステムがサーバーに影響を与えているかを分析するためのテストを行う方法はありますか?XEセッションが作成されたときに実際に何が起こるかを知ることができれば、サーバーへの影響を分析するのに役立ちます。

トリガーを検討し、オーバーヘッドのためにそのオプションを省略しました。しかし、それはインターネットからの情報に基づいて決定されました。



SQL監査を介してキャプチャされたすべてのイベントにXEventsからアクセスできるわけではありません。SQL監査はXEventsの背後にある同じエンジンを利用しますが、それらは別個の機能です。

そうだね。しかし、ある種の負荷テスト(下記参照)を行ったとき、XEは監査よりもオーバーヘッドが多いことがわかりました。監査がバックグラウンドでXEを使用する場合、なぜそれがより多くのオーバーヘッドを引き起こしているのでしょうか?
karun_r 2016年

回答:


3

トリガー、および場合によっては他のオプションに対してSQL Server Auditを試行するための簡単なテストリグを作成しました。テーブルに100万行を挿入するテストでは、ベースライン、SQL監査、およびトリガーにそれぞれ52秒、67秒、159秒かかりました。

試験結果

これは特に科学的ではありませんが、アプローチを比較する1つの方法を提供する可能性があります。スクリプトを確認し、それがあなたに役立つかどうかを確認してください:

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
------------------------------------------------------------------------------------------------

ここでトリガーオプションはうまく機能しませんでしたが、キャプチャしたい内容に応じてトリガーコードを簡略化できます。これにより、SQL監査では使用できないかなり使いやすい形式で古い値と新しい値にアクセスできます。アクティビティの少ない構成テーブルにこの手法を使用しましたが、非常にうまく機能します。何をキャプチャしたいかに応じて、変更データキャプチャを検討することもできます。

試練をどのように進めるか教えてください。幸運を。


3

頭に浮かぶ監査の1つの利点は、オンとオフを切り替える人を自動的に記録することですが、XEはそのままではそれを行いません(ただし、XEの停止/開始を追跡するイベントを見つける場合があります)。また、目的に応じて、2つが異なるデータをキャプチャする場合もあります。

一部のテストについては、データベースのバックアップを作成し、負荷がかかっているアプリケーションのトレースをキャプチャして、XEでの監査/置換による再生/再生を行い、パフォーマンスデータを比較しながらコピーを復元する必要があります。

どのパフォーマンスデータ?それはあなた次第です。いくつかのアイデアについて-Linchi Sheaは、トランザクション/秒に焦点を当てて監査とトレースを比較しましたが、Kehayiasは、バッチ/秒と全体的な再生ランタイムに焦点を当てて、トレースとXEを比較しました。

どちらを読んでも解釈の自由があることを知っておく必要があるため、両方とそのコメントを読むことをお勧めします。リンゴの比較のためにリンゴを手に入れるのは難しい。また、トレース/再生では、負荷が適切にシミュレートされない場合があります。たとえば、アプリケーションが存在しないディスクファイルから大量の一括読み込みを行っている場合などです。

しかし重要なことは、少なくとも1つのことを試すことです。そうすることで、自分の決定を正当化し、残りの人のためにそれについてブログに書くことができます。


監査が監査のオン/オフイベントを自動キャプチャすると言うとき、監査証跡でAUSCアクションタイプについて話しているのですか?また、理想的なパフォーマンステストを行うには、アプリケーションの現在のボトルネックを検討し、監査またはXEのいずれかがそれらを悪化させているかどうかを確認する必要があると思います。
karun_r 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.