SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

Archive for 12月, 2010

第 1 回 Get The Fact セミナーの振り返り その 5

3 comments

今回は [バックアップポリシー] について振り返っていきたいと思います。
# 参加から 2 週間経過したのでテンポよくまとめていかないとだいぶ記憶が薄れてきました…。

セミナーでは以下のような図を元にバックアップポリシーについてのお話しがありました。

image

 

■バックアップの基本的な設定

上の図は復旧モデルを [完全] または [一括ログ] にした場合のバックアップの基本的な設定になります。
# [単純] 復旧モデルの場合は、ログのバックアップが取れませんので、データベースのバックアップのみになります。

セミナーでは日に一度のデータベースバックアップと、一時間おきのログのバックアップで設定というような例でお話をされていたと思います。

SQL Server のバックアップは大きく分けて 3 種類あります。
# ファイル / ファイルグループでのバックアップも取得ができるのですが、今回は割愛しておきます。

  • 完全
  • 差分
  • トランザクションログ

完全 / トランザクションログは上の図で [データベース] [ログ] と書かれているバックアップになります。

[完全バックアップ] は、その時点 (バックアップを実行したタイミング) でのデータまで復元することが可能なバックアップとなります。
完全バックアップはそのバックアップ単体で戻すことが可能ですのでバックアップにはログも含まれています。

 

[差分バックアップ] は、前回の完全バックアップからの差分データのみを含んだバックアップになります。
完全バックアップを元にした差分になりますので、単体で戻すことはできず必ず前回の完全バックアップが必要となります。
image
また、差分バックアップは前回の完全バックアップからの差分データですので、完全バックアップを取得してからの期間が長くなり、全データが更新された状態になってしまうと、完全バックアップ相当のバックアップファイルのサイズとなります。

 

[トランザクションログバックアップ] は、ログレコードのバックアップになります。
復旧モデルのときにもお話しがあったのですが、復旧モデルを [完全] [一括ログ] にしている場合は必須になるバックアップとなります。
これらの復旧モデルに関しては、ログレコードは自動的に切り捨てはされず、バックアップを取得したタイミングで切り捨てが行われ、切り捨てられた個所が再利用可能となります。
そのため、ログのバックアップを取得しないとログがずっと蓄積された状態となり、ログ領域のディスクが枯渇することになります。
ログのバックアップは障害発生時に重要となるバックアップのため、できるだけ短い間隔で取得することが重要であるとセミナーではお話がありました。
# 1 時間おきのログのバックアップというお話はこのタイミングであった気がします。
データベースの完全バックアップを取得していない状態ではログバックアップは取得することはできません。
image

 

バックアップについてですが、以下の資料がわかりやすいと思います。
SQL Server 2000 の資料ですが、それ以降のバージョンでも考え方は同じですので。
第 4 章 バックアップと復元

 

■定期的なバックアップの設定

定期的なバックアップの設定方法として、[メンテナンスプランウィザード] によるバックアップの設定が紹介されていました。

ワンタイムのバックアップであれば、データベースを右クリックして、[タスク] → [バックアップ] からバックアップを取得することが可能です。
image

image

このバックアップに関しては、ワンタイムになりますので定期的なバックアップの取得の設定はできません。

定期的なバックアップをウィザード形式で設定する場合は、セミナーで紹介のあった [メンテナンスプランウィザード] を使用する事で設定ができます。

メンテナンスプランウィザードは [管理] → [メンテナンス プラン] → [メンテナンス プラン ウィザード] から起動することができます。
image

メンテナンス プラン ウィザードを使用することで、データベースのメンテナンスをする仕組みを数ステップで設定が可能となります。
image

今回のセミナーでお話しのあったメンテナンスプランに似たものを実際に作ってみたいと思います。

  1. [次へ] をクリックします。
    image
  2. [タスクごとに個別のスケジュールを使用する] を選択して、[次へ] をクリックします。
    image
  3. [データべすのバックアップ (完全)] [データベースのバックアップ (トランザクション ログ)] を選択して、[次へ] をクリックします。
    image
  4. [次へ] をクリックします。
    image
  5. [完全] バックアップの取得対象とバックアップのスケジュールを設定し、[次へ] をクリックします。
    今回は [すべてのデータベース] を毎日 [22:00] に取得するように設定をしています。
    image
  6. トランザクションログのバックアップを取得するデータベースとスケジュールを選択し、[次へ] をクリックします。
    今回は、[すべてのユーザー データベース] を [毎日1 時間置き] にバックアップを取得するように設定しています。
    すべてのユーザー データベースですが復旧モデルが単純以外のデータベースが対象となります。
    image
  7. ログの出力場所を設定し、[次へ ]をクリックします。
    image
  8. [完了] をクリックします。
    image
  9. [閉じる] をクリックします。
    image

以上でメンテナンスプランの作成は完了です。

今回は、[完全 バックアップ] の取得と、[トランザクションログ] のバックアップの取得を設定していますので二つのジョブが SQL Server エージェントに作成されています。

image

作成した 2 つのジョブを手動で実行して、バックアップの取得状況を確認してみたいと思います。
ジョブを手動実行する場合は、対象のジョブを右クリックして、[ステップでジョブを開始] をクリックします。
image

今回は、H ドライブにアックアップを取得しているのですが、データベースのバックアップ (.bak) とトランザクションログのバックアップ (.trn) が取得されていることが確認できます。
image

今回のメンテナンスプランですが、バックアップを取得するたびにタイムスタンプが設定されたバックアップファイルが蓄積されていきます。
image

また、ログに関してもバックアップを実行するたびに蓄積されていきます。
image

このバックアップとログの履歴 (世代) 管理ですが、[メンテナンス クリーンアップ タスク] を使用することで管理することができます。
先ほど作成したメンテナンスプランにこの履歴クリーンアップタスクを組み込んでみたいと思います。

作成したメンテナンスプランは、[管理] → [メンテナンス プラン] の下に作成がされますので、作成したプランをダブルクリックします。
image

そうするとメンテナンスプランのデザインウィンドウが開きます。
image

先ほど作成したプランが、[Subplan_1] [Subplan_2] として設定されています。
今回は [サブプランの追加] をクリックして、[Subplan_3] として[メンテナンス クリーンアップ タスク] を設定します。
image

タスクをダブルクリックすると設定画面になります。
このタスクを使用することで、バックアップファイルとメンテナンスプランのレポートを削除することが可能です。
拡張子単位で指定はできるのですが、ワイルドカードは使えないので、[bak] [tran] 用のバックアップファイル削除タスクを用意します。
imageimage

テキストレポートのクリーンアップタスクとしては以下の内容を設定しました。
image

今回はスケジュールも設定し、このような形でサブプランを設定してみました。
image

今回は 4 週経過したファイルが対象になっていますので、以下の PowerShell を実行して、ファイルの更新日付を変更してみました。
# クリーンアップタスクでファイル操作をする際の日付はファイルの更新日付が検索対象となります。

Get-Item "C:Program FilesMicrosoft SQL ServerMSSQL10_50.SQL2008R2MSSQLLogMaintenancePlan_Subplan_1_20101220221815.txt" | Set-ItemProperty -name LastWriteTime -Value (Get-Date).AddDays(-28)

これで、メンテナンスレポートの日付が 28 日前 (4 週間前) になりました。
image

それでは、作成したクリーンアップタスクんのジョブを実行してみます。
ジョブを実行したことで、先ほどファイルの更新日付を変更したメンテナンスレポートが削除されていることが確認できます。
image

バックアップ ファイルに関しても更新日付が条件に一致するのであれば削除されます。
image
image

メンテナンス プラン ウィザードを使用することでバックアップのメンテナンスプランを GUI のウィザードベースで柔軟に設定することが可能となります。

今回の投稿では設定をしなかったのですが、メンテナンスプランには [データベースの整合性確認] というメンテナンス タスクがあります。

セミナーの中ではこのタスクについてもお話がありました。

次の投稿では、データベースの整合性確認についてまとめてみたいと思います。

Written by Masayuki.Ozawa

12月 20th, 2010 at 9:52 pm

SQL Server のインスタンス ルート ディレクトリを変更した場合の注意点

one comment

SQL Server のインストールですが、インストール時に [インスタンス ルート ディレクトリ] を設定します。
image

インスタンス ルート ディレクトリは任意のディレクトリを指定できますので、デフォルトの [C:Program FilesMicrosoft SQL Server] から変更することが可能です。

このインスタンス ルート ディレクトリですが、変更した際に一点注意点があります。
今回は、C ドライブではなく E ドライブに設定をしてみました。
image

インスタンス ルート ディレクトリ以外は C ドライブに設定しています。
image

SQL Server をインストールすると以下のサービスがインストールされます。

  • SQL Active Directory Helper Service
  • SQL Server
  • SQL Server Agent
  • SQL Server Browser
  • SQL Server VSS Writer

インスタンス ルート ディレクトリに選択したディレクトリには、[SQL Server] [SQL Server Agent] のサービスのファイルが格納されます。
image
image

サービス用のプログラムが C ドライブ以外にあることは問題ないのですが、この状態では Windows Server バックアップで [システム状態] [ベアメタル 回復] のバックアップを取得する際に、SQL Server 用のサービスに必要なプログラムが格納されているドライブも取得対象となります。
# このあたりは、System Writer の VSS Writer が制御しているみたいですね。レジストリ (ImagePath の値) を直接修正して、サービスで使用するプログラムの場所を変更すればインスタンス ルート ディレクトリを取らなくすることもできますが。危険すぎてこの方法は使わないですよね…。

最初は [ベア メタル回復] のバックアップ取得を試してみます。
image

ベア メタル回復を選択すると、自動的にベアメタル回復に必要なドライブが選択されるのですが、C ドライブだけでなく E ドライブも自動的に選択がされます。
E ドライブを外そうとしても以下のメッセージが表示され、ドライブ / ドライブ以下のフォルダを外すことができません。
image

[システム状態] を選択すると、システム状態の回復に必要なものが取得されます。
# ドライブの選択状況は変わらず、内部でシステム状態の回復に必要なものが自動で取得されます。
image

システム状態を選択した際に取得されるバックアップを確認してみます。
3 つの VHD ファイルが作成されています。
image

これですが、[システムで予約済み] (通常にインストールをした際の先頭 100MB) [C ドライブ] [E ドライブ] のバックアップとなっています。

Windows Server 2008 R2 の場合はファイル単位でバックアップが取得できるようになているので、各ドライブのバックアップはシステム状態として必要最低限のファイルがバックアップされています。
# C ドライブであればユーザープロファイルのディレクトリは除外されています。

E ドライブのバックアップを確認してみるとサービスで使用している 2 つのファイルのみが取得されています。
image

Windows Server 2008 R2 であれば、ファイル単位で取れるのでシステム状態を取得した時にインスタンス ルート ディレクトリを C ドライブ以外にしても最小限のファイルがバックアップされることになります。

 

Windows Server 2008 ではどうなるでしょう。

Win
dows Server 2008 では[システム回復を有効にする] がベアメタル回復相当のバックアップとなります。
このオプションを有効にすると、インスタンス ルート ディレクトリに指定したドライブも自動的に選択されます。
image

この動きは、Windows Server 2008 R2 と同じですね。

それでは、システム状態のバックアップを取得するとどうなるでしょう。
Windows Server 2008 の場合は、[wbadmin start systemstate

backup] というコマンドラインを使用して、システム状態だけを取得することが可能です。
# [Start Backup] で取得する場合は、[-allCritical] というオプションを指定します。

システム状態を取得する場合に必要となるファイルが含まれているドライブを自動で判断する動きは Windows Server 2008 R2 と変わりません。
image

Windows Server 2008 の場合は、デフォルトでは先頭の 100MB の領域は作成されないので、2 つの VHD ファイルが取得されます。
image

E ドライブ用に取得された VHD の中身を見てみます。
image

Windows Server 2008 R2 と異なり、サービス以外のファイルも取得されています。

Windows Server 2008 の場合は、ボリューム単位でのバックアップしか取得ができないため、SQL Server のサービスで使用しているファイル以外のものも取得がされます。

そのため、インスタンス ルート ディレクトリのドライブに SQL Server のデータベースを格納していると、Windows Server 2008 ではシステム状態のバックアップでデータベースのファイルも取得がされてしまい、バックアップのファイルサイズが肥大化する可能性があります。

インスタンス ルート ディレクトリを変更することはあまりないかもしれませんが、変更する場合はバックアップの取得で影響がないようにデータベースのファイルを配置するような考慮が必要そうですね。

Written by Masayuki.Ozawa

12月 19th, 2010 at 10:11 pm

LocalSystem 以外で WMI イベント警告を受信

leave a comment

先日、SQL Server の WMI イベント警告について投稿をしました。

WMI イベント警告は SQL Server Agent 経由で実行されるため、SQL Server の権限も SQL Server Agent のサービスアカウントのものになります。

BOL に記載されているのですが、WMI イベント警告で警告を受信するためには、以下の権限が必要となります。

WMI 警告の通知を受信するには、SQL Server エージェントのサービス アカウントに、WMI イベントを含む名前空間、および ALTER ANY EVENT NOTIFICATION に対する権限が許可されている必要があります。

 

SQL Server Agent をローカルシステムアカウント (LocalSystem : NT AUTHORITYSYSTEM) で実行した場合は、特に設定を変更しなくても WMI イベント警告を受信できると思います。

SQL Server Agent を一般ユーザー (Users グループのユーザー) で起動した場合はどうなるでしょう。

イベントの条件に達してもイベントビューアーのアプリケーションに [124] のエラーが出力されて WMI イベント警告が実行されません。
image
image

この挙動の原因ですが、ローカルシステムアカウントの場合は、[ALTER ANY EVENT NOTIFICATION] のサーバーレベルの権限が付与されています。
サーバーレベルの権限は以下のクエリで確認ができます。

EXECUTE? AS LOGIN = ‘NT AUTHORITYSYSTEM’
SELECT SUSER_NAME(), USER_NAME()
SELECT * from fn_my_permissions(NULL, ‘SERVER’) ORDER BY permission_name
REVERT

SQL Server Agent が SQL Server に接続する場合は、[NT SERVICESQLAgent$<インスタンス名>] のログインで実行がされます。
# OS によってはサービスアカウントがそのまま使用されていることもあります。
image

このログインは、Windows 認証になっているので、Windows アカウントを使用したログインとなっています。
Windwos? Server 2008 R2 の場合はこのアカウントはサービス SID になっていて、Windows のログインやグループではなく、サービスに直接関連づいたアカウントになっています。

サービス SID の場合は、上記のクエリだと権限が見えないのですよね…。
サービス SID を使用していない OS (XP / 2003)? の場合は、SQL Server Agent の起動アカウントに、[ALTER ANY EVENT NOTIFICATION] の権限は付与されていませんでした。
ローカルシステム以外で SQL Server Agent を起動しているときは、以下のクエリを実行して、権限を付与する必要があります。

USE [master]
GO
GRANT ALTER ANY EVENT NOTIFICATION TO [NT SERVICESQLAgent$SQL2008R2]

権限を外す場合はこちらになります。
# REVOKE で権限を外します。

USE [master]
GO
REVOKE ALTER ANY EVENT NOTIFICATION TO [NT SERVICESQLAgent$SQL2008R2]

ALTER ANY EVENT NOTIFICATION の権限を付与することで、WMI イベントを SQL Server Agent のサービス起動ユーザーで受信できるようになり、WMI イベント警告を実行できるようになります。

WMI イベントを含む名前空間に関しては、インストール直後の状態の権限で問題は無いようです。

WMI の権限の確認についてですが、ファイル名を指定して実行から MMC を起動して、[WMI コントロール] を追加します。image

MMC に WMI のスナップインを追加した後に、WMI コントロールのプロパティを開きます。
image

WMI コントロールのプロパティが開いたら、[セキュリティ] タブの [RootMicrosoftSqlServerServerEvents<インスタンス名>] を選択して、[セキュリティ] をクリックします。
image

そうすると、WMI 名前空間に対してのセキュリティを確認することができます。
image

SQL Server Agent のサービス SID には、[メソッドの実行] [アカウントの有効化] [セキュリティの読み取り] の権限が付与されています。

WMI イベント警告を実行するために必要な権限はこの権限でよいようで、デフォルトから設定は変更しなくても実行することができました。

サーバーレベルで権限を付与する必要があり、この操作は普段あまりやらない作業だと思いますので、ちょっと戸惑うかもしれないですね。

Written by Masayuki.Ozawa

12月 19th, 2010 at 3:10 pm

Forefront Endpoint Protection 2010 と Security Essentials 2.0 が提供されました

3 comments

先日、エンタープライズ向けのセキュリティ製品である、Microsoft Forefront Endpoint Protection 2010 (FEP) と個人向けの Microsoft Security Essentials 2.0 (MSE) の提供が開始されました。
Microsoft Forefront
Microsoft Security Essentials
MSE は個人向けの製品ですので、インストーラーを実行すればインストールをすることが可能です。

スモールビジネス用として事業で使用する PC 10 台にもインストールすることはライセンス上できますが。

今回提供された、MSE 2.0 ですが、MSE 1.0 からのアップグレードをすることも可能です。
image
image
ライセンス条項に

    1. 本ソフトウェアは、Microsoft Windows オペレーティング システムのエンタープライズ バージョンが実行されているデバイス上では使用できません。

[2011/2/25 修正]
と書いてありますので、エンタープライズバージョン (サーバー OS) で使うと条項に違反すると思いますのでご注意ください。
# インストールできるのと使っていいのかは別になりますので。
本件についてコメントでフィードバックいただきましたので上記を取り消し線にしました。
情報の提供ありがとうございます!!
MSE は Windows Updat 経由でパターンをアップデート / サーバーによる一括管理ができない製品仕様になっているはずですので基本は個人で使用する製品となります。
企業で一括管理、WSUS によるパターンファイルの更新を行いたいといった場合には、Forefront Endpoint Protection 2010 (FPE) を使用することになります。

Windows Update 経由でもパターンファイルの更新は可能です。

これは Forefront という製品ブランドがついているようエンタープライズ向けのセキュリティ製品になります。
FEP はサーバーを立てることで集中管理をすることが可能になりますが、スタンドアロンモードでインストールすることも可能です。
スタンドアロンモードでのインストールですが、FEP 2010 のインストールメディアを入れ、[FEP2010_ja-jpx64client] の [FEPInstall.exe] を実行するとインストールができます。
以前のバージョンである Forefront Client Security (FCS) だと [Clientsetup.exe /NOMOM] といった形でインストールすることで、管理サーバーの配下に置かないスタンドアロンモードになったのですが、FPE だとインストーラーを単純に起動するとスタンドアロンモードになるみたいですね。
デフォルトでインストールすとスタンドアロンモードなので一括管理するモードはどうやって導入をするのかは調べないといけないですね…。
現状 TechNet のライブラリは英語版のみとなっているようです。
下のリンクはツリービューを表示させたかったので意図的に英語にしていますが en-us → ja-jp に URL を変更してもブログの投稿時点では英語版のヘルプになっています。
FEP2010 Client Help
インストール時の画面キャプチャがこちらです。
特に設定を入力することもなく、ウィザードベースで進んでいきます。
imageimage
imageimage
imageimage
image
以上でインストールは完了です。
image
image
二つの製品ですが、エンジン部は共通だったはずですので、定義情報に関しても同じバージョンになっていますね。
以前のバージョンである、FCS の環境にインストールしてみたところ特にアップグレードというメッセージは表示されずに、新規インストールと同じウィザードが起動してきたのですが、設定が引き継がれてアップグレードインストールされていました。

再起動が必要でしたが。

image
検証 / 評価環境で TechNet サブスクリプションを使用している方は結構多いかと思いますが、FPE は TechNet サブスクリプションで入手ができ、ウイルス対策ソフトとして使用することが可能です。
評価環境のウイルス対策をどうしようと考えられている方は FEP をご利用してみてはいかがでしょう。

MSE はライセンス的にサーバー OS でどうさせるのは今のライセンス条項の記述では NG だと思いますので。

Written by Masayuki.Ozawa

12月 18th, 2010 at 3:57 pm

Posted in Forefront

Tagged with , ,

第 1 回 Get The Fact セミナーの振り返り その 4

leave a comment

今回は [パフォーマンス条件警告] について振り返ってみたいと思います。

セミナーの中で SQL Server のパフォーマンス条件警告をしようして、ログの使用状況が一定の閾地に達した場合にログのバックアップを取得して、ログを切り捨てるという方法が紹介されました。

それでは、パフォーマンス条件警告についてまとめていきたいと思います。

■パフォーマンス条件警告設定の流れ

パフォーマンス条件警告ですが、[SQL Server Agent] を使用して動作します。
image

設定は

  1. 警告の条件を設定
  2. 警告が発生した際に実行する SQL Server Agent のジョブを設定
  3. 警告が発生したことの通知方法を設定

という流れになります。
# 実際の設定は順不同でジョブと通知方法は必須ではないですが。

 

■パフォーマンス条件警告を設定

それでは、実際にパフォーマンス条件警告を設定していきたいと思います。
今回はセミナーでお話しのあったものと同じ設定を行っていきます。

  1. [警告] を右クリックして、[新しい警告] をクリックします。
    image
  2. 警告の条件を設定します。
    今回は以下の内容で設定を行っています。
    image
    TEST データベースのログが 200,000KB 使用された場合に警告を発生するように設定しています。
  3. [応答] の [ジョブの実行] を有効にして、[新しいジョブ] をクリックします。
    image
    今回は警告を作成する作業の流れで、新しいジョブを作成していますが、事前に作成したジョブを使う事も可能です。
  4. ジョブの [名前] を入力します。
    image
  5. [ステップ] の [新規作成] をクリックします。
    image
  6. ログのバックアップを取得するためのステップを作成し、[OK] をクリックします。
    # 今回のパフォーマンス条件警告は後でスクリプト化したものを記載しますのでコマンドの内容はここでは割愛します。
    image
  7. [OK] をクリックします。
    image
  8. [OK] をクリックします。
    image

以上で設定は完了です。
image

今回は通知設定はしていませんが、通知は以下の方法で行う事ができます。
image

 

それでは実際にデータを追加して挙動がどのように変わるかを試してみたいと思います。
今回も自動チェックポイントは無効にしています。

パフォーマンス条件警告を無効にしている場合の状態はこのようになります。
# 作成した警告は、個別に無効化することができます。
image

ログの書き込み待ちとバックアップ処理時間は 2 軸にしていますが、これらは発生していないことが確認できます。

それでは、パフォーマンス条件警告を有効にして同じ処理を実行してみます。
image
こちらも、バックアップ処理時間は 2 軸に表示しています。
ログの書き込み待ちに関しては、カウンタがあがっていることを示すために、元の値に 10,000 をかけています。

パフォーマンス条件警告の設定内容が有効になっていますので、ログファイルの使用状況が一定に達したタイミングで自動的にログのバックアップが行われています。(バックアップ処理時間はデータ/ログのバックアップを取得すると発生します。)

今回作成したパフォーマンス条件警告のサンプルスクリプトがこちらになります。

USE [msdb]
GO

/****** Object:  Job [TEST Database Log Backup]    Script Date: 12/16/2010 21:09:09 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]]    Script Date: 12/16/2010 21:09:09 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]’ AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N’JOB’, @type=N’LOCAL’, @name=N'[Uncategorized (Local)]’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N’TEST Database Log Backup’,
        @enabled=1,
        @notify_level_eventlog=0,
        @notify_level_email=0,
        @notify_level_netsend=0,
        @notify_level_page=0,
        @delete_level=0,
        @description=N’使用できる説明はありません。’,
        @category_name=N'[Uncategorized (Local)]’,
        @owner_login_name=N’WIN-1QM471JPL04Administrator’, @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [TEST Database Log Backup]    Script Date: 12/16/2010 21:09:09 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N’TEST Database Log Backup’,
        @step_id=1,
        @cmdexec_success_code=0,
        @on_success_action=1,
        @on_success_step_id=0,
        @on_fail_action=2,
        @on_fail_step_id=0,
        @retry_attempts=0,
        @retry_interval=0,
        @os_run_priority=0, @subsystem=N’TSQL’,
        @command=N’BACKUP LOG [TEST] TO  DISK = N”F:BackupSQL2008R2TEST.bak” WITH NOFORMAT, INIT,  NAME = N”TEST-トランザクション ログ  バックアップ”, SKIP, NOREWIND, NOUNLOAD,  STATS = 10
GO
‘,
        @database_name=N’TEST’,
        @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

GO

 

EXEC msdb.dbo.sp_add_alert @name=N’TEST Database Log Auto Backup’,
        @message_id=0,
        @severity=0,
        @enabled=0,
        @delay_between_responses=0,
        @include_event_description_in=0,
        @category_name=N'[Uncategorized]’,
        @performance_condition=N’MSSQL$SQL2008R2:Databases|Log File(s) Used Size (KB)|TEST|>|200000′,
        @job_id=N’e5518186-0c48-4c08-a14c-3c5c285730ef’
GO

このスクリプトですが、[INIT] を指定してログのバックアップを取得しています。
本来の運用では、この指定は NG です。
# テスト用でログのバックアップを蓄積したくなかったので INIT でバックアップを上書きしています。
ログのバックアップはログチェーンという考えがあり、連続したログのバックアップが担保されている必要があります。
ログチェーンが途切れてしまうとログを使用したリストアができませんので、本番運用で使う場合は [NOINIT] かログファイルの名称を動的に生成するようにしてログを上書きしないようにする必要があります。

■Twitter での質問について

セミナー中に Twitter で以下のような質問がありました。
「オンライン中のトランザクションログバックアップのパフォーマンス劣化はどれくらいなのでしょうか?」

ログのバックアップをするとログの書き込み待ちが発生しているのが上のグラフで確認することができます。
# 今回の環境では 200 MB 程度のログのバックアップを書き込む際には、書き込み待ちは最大で 7ms 程度になっていました。

グラフではなくWRITELOG の待ち事象でも比較をし手みたいと思います。

パフォーマンス条件警告を設定していない場合はこのような待ち事象になります。

image
image

waiting_tasks_count = 619,844 ? 519,766 = 100,078
wait_time_ms = 459,265 ? 396,561 = 62,704

パフォーマンス条件警告を設定した場合はこのようになります。

image
image

waiting_tasks_count = 720,408 ? 619,881 = 100,527
wait_time_ms = 532,001 ? 459,405 = 72,596

ログのバックアップをしている最中はログの使用状況がなだらかになりますのでログの書き込みにも多少の影響が発生します。

また、BOL に以下のように書かれているようにバックアップの実行を行うと CHECKPOINT が発生します。

チェックポイントは次の状況で作成されます。

  • CHECKPOINT ステートメントが明示的に実行された場合。接続を確立するために、現在のデータベースでチェックポイントが作成されます。
  • データベースで最小ログ記録操作が実行された場合。たとえば、一括ログ復旧モデルを使用しているデータベースで一括コピー操作が実行された場合です。
  • ALTER DATABASE を使用して、データベース ファイルが追加または削除された場合。
  • SHUTDOWN ステートメント、または SQL Server (MSSQLSERVER) サービスを停止することによって、SQL Server のインスタンスが停止された場合。どちらの場合でも、SQL Server のインスタンスの各データベースでチェックポイントが作成されます。
  • データベースの復旧にかかる時間を短縮するために、SQL Server のインスタンスにより、各データベースで定期的に自動チェックポイントが作成されている場合。
  • データベースのバックアップが作成された場合。
  • データベースのシャットダウンが必要な動作が実行された場合。たとえば、AUTO_CLOSE が ON に設定されていて、データベースへの最後のユーザー接続が終了した場合、またはデータベースの再起動が必要なデータベース オプションが変更された場合です。

データベースのバックアップにはログのバックアップも含まれています。
先ほどのグラフにチェックポイントの発生状況も追加してみます。
image

バックアップのタイミングに合わせてチェックポイントが発生していることが確認できます。
チェックポイントが発生するとメモリ上のダーティーページをデータファイルに書きだしますので、データファイルに対しても負荷がかかることになります。

この辺はディスクの性能にも依存するのでどれくらいというのは難しいところなのですが、ログの書き込み待ち + チェックポイントによるデータファイルへの書き出しを劣化分として見込んでおく必要があると思います。
# この辺はディスク性能とドライブ構成に依存するところがあるのですよね…。

 

■WMI イベント警告

これは警告のちょっとした応用なのですが、パフォーマンス条件警告ではなく、[WMI イベント警告] を使用することでイベントを受信してジョブを実行することが可能となります。

例えば、ロックエスカレーションが発生した場合にそのイベントを受信してテーブルにロックエスカレーションが発生した時に実行されたクエリを保存してくれるような警告が作れると運用で便利そうですよね。

WMI イベント警告を使用すると、イベントを受信して特定のジョブを実行するということができるようになります。
# イベントを取得してログに出すだけであれば SQL トレースでもできるのですけどね。

BOL には [サンプル : WMI Provider for Server Events の使用による SQL Server エージェント警告の作成] という形でデッドロックをトラップしてテーブルにデータを書きだすサンプルが紹介されています。
# サンプル : WMI Provider for Server Events の使用による SQL Server エージェント警告の作成

ただし、内容に一か所誤りがあり、

@command= N’INSERT INTO DeadlockEvents (AlertTime, DeadlockGraph) VALUES (getdate(), N”$(ESCAPE_SQUOTE(WMI(TextData))))’

@command= N’INSERT INTO DeadlockEvents (AlertTime, DeadlockGraph) VALUES (getdate(), N”$(ESCAPE_SQUOTE(WMI(TextData))))’

にしないと動かなかったはずですが。
# シングルクォート × 2 が足りていないのですよね…。

WMI イベント警告を使用するための事前準備として 2 つの作業があります。

  1. 対象のデータベースで [Service Broker] を有効にする。
    WMI イベントを受信するために対象のデータベースで [Service Broker] を有効にします。
    BOL に以下のように記載されています。

    SQL Server エージェントが WMI イベントを受信するには、msdb および AdventureWorks2008R2 で Service Broker が有効化されている必要があります。

    msdb に関してはデフォルトで Service Broker が有効になっているはずなのですが、ユーザーデータベースではデフォルトでは無効になっています。
    Service Broker を有効にするためにはデータベースのプロパティを開いて、[Broker が有効][True] にする必要があります。
    image
    ただし、この変更をする際にはデータベースに対して [LCK_M_X] (排他ロック) を取得しにいきますので、対象のデータベースに接続中のユーザーがいると変更できません。
    今回は、SQL Server のサービスを再起動して、サクッと全ロックを外してから実行してしまいました。
    クエリで設定を変更する場合は以下のクエリを実行します。
    # DB 名は適宜変更する必要があります。

    USE [master]
    GO
    ALTER DATABASE [TEST] SET  ENABLE_BROKER WITH NO_WAIT
    GO

  2. SQL Server エージェントで [トークンの置き換え] を有効化
    WMI イベント警告を使用した場合、SQL Server のジョブステップの中で WMI のイベントのプロパティを使用することが可能です。
    WMI のプロパティを使用する場合は、SQL Server エージェントで [トークンの置き換え] を有効にする必要があります。
    たとえば、ロックエスカレーションが発生した際クエリ (SQL) を取得する場合には、WMI(TextData) というように記述をするのですが、[トークンの置き換え] が有効になっていないとこの設定がそのまま文字データ (WMI(TextData) という単純な文字列) として認識されてしまいます。
    WMI(TextData) → 実行されていたクエリ に変換するためには、トークンの置き換えを有効にする必要があります。
    # ジョブ ステップでのトークンの使用

    ロックエスカレーション時のクエリは SQL Server 2008 からでないと取得できなかった気もします…。

    トークンの置き換えはSQL Server エージェントのプロパティから [警告システム] を選択して、[警告に応答するすべてのジョブのトークンを置き換える] を有効にします。
    image
    クエリで有効にする場合は、以下のような内容になります。

    USE [msdb]
    GO
    EXEC msdb.dbo.sp_set_sqlagent_properties @email_save_in_sent_folder=1,
            @alert_replace_runtime_tokens=1

以上で、事前準備は完了です。

基本的な流れはパフォーマンス条件警告と変わりません。
WMI イベント警告特有な内容としては、WMI の名前空間を指定するのとクエリを WQL ステートメントで記載する箇所になります。

名前空間に関しては通常の WMI の名前空間を指定すれば問題ありません。
SQL Server のサーバーイベントに関しては以下の指定をします。

\.rootMicrosoftSqlServerServerEvents<インスタンス名>

私の環境ではこのような指定ですね。
[\.rootMicrosoftSqlServerServerEventsSQL2008R2]

WQL ステートメントを記載するためには、イベント名を記載しなくてはいけないのですが、イベント名は [wbemtest.exe] (Windows Management Instrumentation テスト) を使用すると簡単に確認することができます。
# Windows Server 2008 R2 だと標準で入っています。
image

[接続] をクリックして、SQL Server の名前空間に接続をします。
image

名前空間に接続をしたら、[クラスの列挙] をクリックします。
[再帰] 選択して [OK] をクリックするとクラスの一覧が取得できます。
image

クラスとして表示されたものが WMI イベント警告で受信できるイベントになります。
image
今回はロックエスカレーションを受信したいので、[LOCK_ESCALATION] というイベントを受信することになります。
LOCK_ESCALATION をダブルクリックするとプロパティを取得することができます。
このプロパティ名がトークンの置き換えで使用できる WMI のプロパティ名になります。
image

 

WMI イベント警告としては以下のような設定を行います。
image

続いて応答で使用するジョブを作成します。
今回は発生時刻 / データベース名 / 実行していたクエリの情報をテーブルに格納したいと思います。
そのため、以下のテーブルを事前に作成しておきます。
# 今回は [TEST] というデータベース上に作成しています。

CREATE TABLE dbo.LockEscalationEvent
    (
    EventDate datetime NULL,
    DatabaseName nvarchar(128) NULL,
    SQL nvarchar(MAX) NULL
    )  ON [PRIMARY]
     TEXTIMAGE_ON [PRIMARY]
GO

ジョブの名前は適当なものを設定します。
image

ジョブには以下のような内容を設定します。
image

コマンドにはトークンの置き換えを使用して、WMI のプロパティを ESCAPE_SQUOTE を使って、プロパティ内にシングルクォートが存在している場合は修飾するように指定をしたクエリを設定しています。

以上で、WMI イベント警告の設定は完了です。

それでは実際にロックエスカレーションを発生させて正常に動作するかを見ていきたいと思います。
image
UPDLOCK を設定して、トランザクション内で大量のデータを SELECT したためロックエスカレーションが発生しています。
そのあとに、JobStep が実行されていますね。
# JobStep は SQL Server Agent サービスの起動アカウントで SQL Server に接続して実行されています。
今回は LocalSystem アカウントで実行しています。

最後の JobStep を確認すると、INSERT 文が実行されていることが確認できます。
image

INSERT 文ですが、トークンの置き換えにより WMI のプロパティが文字列に置き換えられて実行されているのが確認できますね。
作成したテーブルを確認してみます。
image

イベントが発生した日と対象のデータベース、クエリがテーブルに格納されています。

WMI イベント警告を使用することで特定のイベント受信時にジョブを動かくすことができますのでうまく使うと運用が楽になるかもしれないですね。
今回作成した警告とジョブのサンプルスクリプトは以下になります。

USE [msdb]
GO

/****** Object:  Job [JOB LockEscalation]    Script Date: 12/16/2010 23:10:33 ******/
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
/****** Object:  JobCategory [[Uncategorized (Local)]]]    Script Date: 12/16/2010 23:10:33 ******/
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]’ AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N’JOB’, @type=N’LOCAL’, @name=N'[Uncategorized (Local)]’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

END

DECLARE @jobId BINARY(16)
EXEC @ReturnCode =  msdb.dbo.sp_add_job @job_name=N’JOB LockEscalation’,
        @enabled=1,
        @notify_level_eventlog=0,
        @notify_level_email=0,
        @notify_level_netsend=0,
        @notify_level_page=0,
        @delete_level=0,
        @description=N’使用できる説明はありません。’,
        @category_name=N'[Uncategorized (Local)]’,
        @owner_login_name=N’WIN-1QM471JPL04Administrator’, @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
/****** Object:  Step [Step LockEscalation]    Script Date: 12/16/2010 23:10:33 ******/
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N’Step LockEscalation’,
        @step_id=1,
        @cmdexec_success_code=0,
        @on_success_action=1,
        @on_success_step_id=0,
        @on_fail_action=2,
        @on_fail_step_id=0,
        @retry_attempts=0,
        @retry_interval=0,
        @os_run_priority=0, @subsystem=N’TSQL’,
        @command=N’INSERT INTO
    dbo.LockEscalationEvent
VALUES(
    GETDATE(),
    N”$(ESCAPE_SQUOTE(WMI(DatabaseName)))”,
    N”$(ESCAPE_SQUOTE(WMI(TextData)))”
)
‘,
        @database_name=N’TEST’,
        @flags=0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)’
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
COMMIT TRANSACTION
GOTO EndSave
QuitWithRollback:
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION
EndSave:

GO

 

USE [msdb]
GO

/****** Object:  Alert [WMI Lock Escalation]    Script Date: 12/16/2010 23:10:16 ******/
EXEC msdb.dbo.sp_add_alert @name=N’WMI Lock Escalation’,
        @message_id=0,
        @severity=0,
        @enabled=1,
        @delay_between_responses=0,
        @include_event_description_in=0,
        @category_name=N'[Uncategorized]’,
        @wmi_namespace=N’\.rootMicrosoftSqlServerServerEventsSQL2008R2′,
        @wmi_query=N’SELECT * FROM LOCK_ESCALATION’,
        @job_id=N’6315f399-7921-4431-a4d1-89135a792fa9′
GO

パフォーマンス条件警告と WMI イベント警告を使用することでデータベースの特定の状態を受信してジョブを実行することが可能になります。
# WMI イベント警告は良い機会だったのでついでにまとめたものですが。

パフォーマンス条件警告でログのバックアップを取るのは今まで考えていなかったので、なるほどと思いました。

この後には [バックアップポリシーの検討] ということで、バックアップタクトの一例や障害発生時の復元の概要についてのお話がありました。

次の投稿では、バックアップポリシーについてまとめてみたいと思います。

Written by Masayuki.Ozawa

12月 16th, 2010 at 7:39 pm