web-dev-qa-db-ja.com

DBを使用する最後の人のログイン名またはユーザー名を見つける

上司は、そのDBを使用する最後の人のサイズと名前とともに、DB名のリストを要求しました。私は、DBが最後にアクセスされたのはいつか、だれがアクセスしたかについてのリソースを見つけました。どうすればこれを解決できますか?

SQL2008R2が使用されており、これまでのところ私はこれを持っています:

exec sp_MSForEachDB '
use ?
select ''?'', (SUM(df.size)*8)/1024 as ''Size (MB)''
from sys.database_files as df
'

回答の最後の人の側面が曖昧または緩いものであっても問題ありません。つまり、最近漠然と近づいてきた人であれば、「OK」です。

1
Paul

サーバーが信頼できる期間稼働している場合(少なくとも1つのビジネスサイクルなど)、sys.dm_db_index_usage_statsのようなDMVを使用して、データベース内の任意のテーブルに対して読み取りまたは書き込みが行われたことを確認できます。

whoデータベースを最後に「使用」したことを確認する信頼できる方法はありません。 SQL Serverは、実質的な何かをしない限り、この情報をログに記録しません(たとえば、ユーザーがオブジェクトを作成または削除したことがわかる場合があります デフォルトのトレースで が、これは決して最後のことではありません。データベースにアクセスする人、またはそれが最後の場合データベースにアクセスした人)。

データベースファイルのサイズについては、sp_MSforeachdbを実際に使用する必要はありません。とにかくそのメソッドを使用するべきではありません。理由は次のとおりです。

この場合、とにかくすべてのデータベースをループ処理する必要はありません。この情報はビューmaster.sys.master_filesに複製されます。

SELECT 
  d.name, 
  [Size (MB)] = SUM(mf.size)*8/1024
FROM master.sys.databases AS d
INNER JOIN master.sys.master_files AS mf
ON d.database_id = mf.database_id
GROUP BY d.name;

サポートされていないデータベースの束を通じて何かをする必要がある場合は、マスターの何かでサポートされていないsp_MSforeachdbを使用するよりも、このタイプの手法を使用します。

DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += N'SELECT ''' + name + ''', (SUM(df.size)*8)/1024 as [Size (MB)]
  from ' + QUOTENAME(name) + '.sys.database_files as df;';
EXEC sp_executesql @sql;

(余談ですが、エイリアスを区切るために'single quotes'を使用しないでください。[square brackets]を使用してください。前者はいくつかの形式で非推奨です- here および here)を参照してください -とにかくエイリアスを文字列リテラルのようにします。)

「いつ」の部分については、 ここに私の答え からコピーします:

SQL Serverは、実際にはデータベースアクセスを希望どおりに追跡していません。少なくとも後方に移動します(サーバー側のトレース、拡張イベント、監査などを設定できます)。

使用できるボールパークは1つあります。インデックスの使用状況とプロシージャ/トリガー/クエリの統計を追跡するDMVです。例えば:

;WITH d AS
(
  SELECT d = database_id, name FROM sys.databases
  WHERE state = 0 AND database_id BETWEEN 5 AND 32766
),
index_usage(d,lsk,lsc,llk,lupd) AS
(
  SELECT database_id, MAX(last_user_seek), MAX(last_user_scan),
    MAX(last_user_lookup), MAX(last_user_update)
  FROM sys.dm_db_index_usage_stats
  WHERE database_id BETWEEN 5 AND 32766
  GROUP BY database_id
),
proc_stats(d,lproc) AS
(
  SELECT database_id, MAX(last_execution_time) 
    FROM sys.dm_exec_procedure_stats
    WHERE database_id BETWEEN 5 AND 32766
    GROUP BY database_id
),
trig_stats(d,ltrig) AS
(
  SELECT database_id, MAX(last_execution_time)
    FROM sys.dm_exec_trigger_stats
    WHERE database_id BETWEEN 5 AND 32766
    GROUP BY database_id
),
query_stats(d,lquery) AS
(
  SELECT t.[dbid], MAX(s.last_execution_time) 
    FROM sys.dm_exec_query_stats AS s
    CROSS APPLY sys.dm_exec_sql_text(s.plan_handle) AS t
    WHERE t.[dbid] BETWEEN 5 AND 32766
    GROUP BY t.[dbid]
)
SELECT d.name,i.lsk,i.lsc,i.llk,i.lupd,p.lproc,t.ltrig,q.lquery
FROM d LEFT OUTER JOIN index_usage AS i ON d.d = i.d
LEFT OUTER JOIN proc_stats  AS p ON d.d = p.d
LEFT OUTER JOIN trig_stats  AS t ON d.d = t.d
LEFT OUTER JOIN query_stats AS q ON d.d = q.d;

ストアドプロシージャがなく、sys.dm_exec_query_statsにあるクエリが複数のデータベースを参照している可能性があるため、これらの統計は完全に信頼できるわけではないことに注意してください。

また、SQL Serverの再起動時、データベースのデタッチ/アタッチまたは復元時、またはデータベースの自動クローズ時にもリセットされ、場合によっては、キャッシュ内に残っているプラ​​ン(別のデータベースがその数分以内に完全に引き継ぎます)。したがって、過去を調べている場合、ビジネスサイクル全体でこれらのことが何も起こっていないことがわかっていない限り、データベースが使用されているかどうかを判断するためにこれらの数値だけに頼ることはありません(自動化されているプロセスも存在する可能性があります)データベースを削除するときにこれらの自動化されたプロセスが失敗することを気にしない場合でも、データベースは最新のように見えます)。

もう1つの注意点は、特定のインデックスアクセスがインデックス使用状況ビューで追跡されない可能性があることです。たとえば、メモリ最適化テーブルを追加するSQL Server 2014では、これらのハッシュインデックスに対するアクティビティはこの方法でキャプチャされません(sys.dm_db_xtp_hash_index_statsなど、アクティビティがキャプチャされると思われるビューには日付が含まれていません)/time列)。 SQL Server 2014とインメモリOLTP( "Hekaton")を使用している場合は、それらのオブジェクトをカバーするための調査を追加することをお勧めします(オブジェクトがデータベース)。

そしてもう1つの注意点は、sys.dm_exec_query_statsによってキャプチャされたクエリが誤検知になる可能性があることです。たとえば、データベースにfilestream/filetableがある場合、システムによってこれらのクエリが時々実行されていることがわかります。

select table_id, item_guid, oplsn_fseqno, oplsn_bOffset, oplsn_slotid
from [database].[sys].[filetable_updates_<some_id>] with (readpast) order by table_id

したがって、上記のクエリに追加のフィルタリングを追加して、それらを除外することができます(必要なクエリを誤ってフィルタで除外しない限り)。これはおそらくその派生テーブルへの安全な追加です:

AND t.[text] NOT LIKE N'%oplsn_fseqno%'

結局のところ、開発環境で行う最も安全なことは、1週間オフラインであることが不明なデータベースを取得することです。誰も不平を言わない場合、それらをバックアップし、それらを落としてください。誰かが行方不明になっていることに気付くのに1週間以上かかる場合は、いつでも(そこにあるか、他の場所に)復元できます。

私もこれについて少しブログを書いています:

4
Aaron Bertrand