トピック about_Transactions 簡易説明 Windows PowerShell でトランザクション処理を管理する方法について説明します。 詳細説明 トランザクションは、Windows PowerShell 2.0 以降でサポートされます。トランザクションの開 始、トランザクションに参加させるコマンドの指定、トランザクションのコミットとロールバックなどを 行うことができます。 トランザクションについて Windows PowerShell におけるトランザクションとは、論理的な単位として管理される 1 つまた は複数のコマンドのまとまりです。トランザクションを完了 ("コミット") すると、そのトランザク ションの影響下にあるデータが変更されます。トランザクションは、完全に元に戻す ("ロールバック" する) こともできます。トランザクションをロールバックすると、その影響下にあるデータは変更さ れません。 1 つのトランザクション内の一連のコマンドは 1 つの単位として管理されるので、コマンドはすべて コミットされるか、すべてロールバックされるかのいずれかとなります。 トランザクションは、金融取引向けのデータベース処理に代表されるデータ処理で広く利用されています。 トランザクションが最もよく利用されるのは、最悪の状況は何かを考えたときに、一連のコマンドがすべて 失敗するよりも、"一部の" コマンドだけが失敗することの方が問題となるような場合です。そのままにすると、 システムが障害状態や本来あり得ない状態など、復旧が難しく解釈不能な状態に陥るようなケースで、 トランザクションが有効に活用されています。 トランザクションのコマンドレット Windows PowerShell には、トランザクションの管理を目的としたコマンドレットをいくつか備え ています。 コマンドレット 説明 -------------- --------------------------------- Start-Transaction 新しいトランザクションを開始します。 Use-Transaction トランザクションにコマンドまたは式を追加します。コマンドに 使用するオブジェクトはトランザクション対応であることが必要です。 Undo-Transaction トランザクションをロールバックし、データが変更されないよ うにします。 Complete-Transaction トランザクションをコミットします。トランザクションの 対象となるデータは変更されます。 Get-Transaction アクティブなトランザクションに関する情報を取得します。 トランザクションに関連したコマンドレットの一覧について参照するには、次のコマンドを入力してください。 get-command *transaction コマンドレットの詳細について参照するには、次のコマンドを入力してください。 get-help <cmdlet-name> -detailed 次にその例を示します。 get-help use-transaction -detailed トランザクション対応の要素 トランザクションに参加するには、コマンドレットとプロバイダーの両方がトランザクションをサポー トしている必要があります。この機能は、トランザクションの対象となるオブジェクトに組み込まれています。 Windows Vista では、Windows PowerShell レジストリ プロバイダーがトランザクションをサ ポートしています。TransactedString オブジェクト (Microsoft.PowerShell.Commands.Management.TransactedString) は、Windows PowerShell が動作するすべてのオペレーティング システムで使用できます。 トランザクションをサポートする Windows PowerShell プロバイダーは他にもあります。実際の セッション中に、トランザクションをサポートする Windows PowerShell プロバイダーを探すに は、次のコマンドを使用して、プロバイダーの Capabilities プロパティに含まれる "Transactions" という値を検索します。 get-psprovider | where {$_.Capabilities -like "*transactions*"} プロバイダーの詳細については、該当するプロバイダーのヘルプを参照してください。 プロバイダーのヘルプを取得するには、次のように入力します。 get-help <provider-name> たとえば、Registry プロバイダーのヘルプを取得するには、次のように入力します。 get-help registry USETRANSACTION パラメーター トランザクションをサポートできるコマンドレットは、UseTransaction パラメーターを備えています。 これは、コマンドをアクティブなトランザクションに参加させるためのパラメーターです。このパラメ ーターはフルネームで使用することも、"usetx" というエイリアスで使用することもできます。 このパラメーターは、セッションにアクティブなトランザクションが存在する場合にのみ使用できます。 アクティブなトランザクションがないにもかかわらず、UseTransaction パラメーターを備えたコマンド を入力した場合、エラーが発生します。 UseTransaction パラメーターを備えたコマンドレットを探すには、次のように入力します。 get-help * -parameter UseTransaction Windows PowerShell のコアでは、Windows PowerShell プロバイダーに対して使用できるよう に設計されたコマンドレットはすべてトランザクションをサポートしています。したがって、トランザ クションの管理には、プロバイダー コマンドレットを使用することができます。 Windows PowerShell プロバイダーの詳細については、「about_Providers」を参照してください。 トランザクション オブジェクト Windows PowerShell では、トランザクションが、System.Management.Automation.Transaction というトランザクション オブジェクトによって表されます。 このオブジェクトには、次のプロパティがあります。 RollbackPreference: 現在のトランザクションに対して設定されたロールバック設定を保持します。ロールバック設定 は、Start-Transaction を使用してトランザクションを開始するときに設定できます。 ロールバック設定によって、トランザクションが自動的にロールバックされる条件が決まります。 有効な値は、Error、TerminatingError、および Never です。既定値は Error です。 Status: トランザクションの現在の状態を保持します。有効な値は Active、Committed、および RolledBack です。 SubscriberCount: トランザクションのサブスクライバー数を保持します。別のトランザクションの進行中にトランザクションを 開始すると、トランザクションにサブスクライバーが追加されます。サブスクライバーがトランザクションを コミットすると、サブスクライバーの数が減らされます。 アクティブなトランザクション Windows PowerShell では、同時に複数のトランザクションがアクティブになることはありませ ん。管理できるのは、アクティブなトランザクションのみです。同じセッションで同時に複数のトラン ザクションが進行する場合もありますが、アクティブになるのは、最後に開始されたトランザクションだけです。 したがって、トランザクションのコマンドレットを使用する場合に、特定のトランザクションを指定することはできません。 コマンドはアクティブなトランザクションに常に適用されます。 この動作の典型的な例は、Get-Transaction コマンドレットです。Get-Transaction コマンド を入力した場合、Get-Transaction は常に単一のトランザクション オブジェクトを取得します。こ れは、アクティブなトランザクションを表すオブジェクトです。 別のトランザクションを管理するには、まず、アクティブなトランザクションをコミットするか、 ロールバックして完了させる必要があります。トランザクションを完了させると、その 1 つ前のトランザ クションが自動的にアクティブになります。トランザクションは、それが開始された順序とは逆にアクティ ブになるので、最後に開始されたトランザクションが常にアクティブになります。 サブスクライバーと別トランザクション 既存のトランザクションの進行中に別のトランザクションを開始した場合、既定では、新しいトランザクションは 開始されません。代わりに、現在のトランザクションに "サブスクライバー" が追加されます。 1 つのトランザクションに複数のサブスクライバーが存在する場合、どこかの時点で Undo- Transaction コマンドを 1 回実行するだけで、すべてのサブスクライバーのトランザクション全 体がロールバックされます。ただし、トランザクションをコミットする場合は、各サブスクライバーに ついて、Complete-Transaction コマンドを入力する必要があります。 トランザクションのサブスクライバー数を調べるには、トランザクション オブジェクトの SubscriberCount プロパティを確認します。たとえば、次のコマンドでは、Get-Transaction コマンドレットを使用して、アクティブなトランザクションの SubscriberCount プロパティの値 を取得しています。 (Get-Transaction).SubscriberCount サブスクライバーが追加されるという振る舞いが既定の動作として採用されている理由は、別のトランザクションの 進行中に開始されたトランザクションは元のトランザクションに関連しているのが通例であるためです。トランザ クションを含んだスクリプトから、それ自身のトランザクションを含んだヘルパー スクリプトを呼び出すというのは、 きわめて一般的なモデルです。これらのトランザクションには相互関係があるので、ロールバックまたはコミットも、 1 つのまとまりとして実行する必要があります。 ただし、Start-Transaction コマンドレットの Independent パラメーターを使用することによっ て、現在のトランザクションとは異なる別のトランザクションを開始することもできます。 独立した別のトランザクションを開始すると、Start-Transaction によって、新しいトランザクシ ョン オブジェクトが作成され、その新しいトランザクションがアクティブなトランザクションになり ます。独立した別のトランザクションは、元のトランザクションに影響を与えることなく、コミットま たはロールバックすることができます。 独立した別のトランザクションがコミットまたはロールバックされて完了すると、元のトランザクションが 再度アクティブになります。 データの変更 トランザクションを使用してデータを変更する場合、トランザクションをコミットするまで、その対象となるデータは変更 されません。ただし、同じデータが、トランザクションに参加していないコマンドによって変更される可能性はあります。 トランザクションを使用して共有データを管理する場合は、この点に注意してください。通常、データベースは、 使用中のデータをロックすることによって、他のユーザーや他のコマンド、スクリプト、関数による変更を防ぐメ カニズムを備えています。 ただし、ロックは、あくまでデータベースの機能です。トランザクションに関連した機能ではありま せん。トランザクション対応のファイル システムまたはその他のデータ ストアを使用している場合、 トランザクションの進行中にデータが変更される可能性があります。 例 このセクションでは、Windows PowerShell レジストリ プロバイダーを使用した例を紹介していま す。レジストリ プロバイダーに関する知識が必要となります。レジストリ プロバイダーの詳細について は、「get-help registry」と入力してください。 例 1: トランザクションのコミット トランザクションを作成するには、Start-Transaction コマンドレットを使用します。次のコマンド は、既定の設定でトランザクションを開始します。 start-transaction コマンドをトランザクションに参加させるには、コマンドレットの UseTransaction パラメーターを 使用します。既定では、コマンドはトランザクションに参加しません。 たとえば、次のコマンドは、HKCU: ドライブの Software キーに移動するコマンドですが、トランザ クションには参加していません。 cd hkcu:\Software 次のコマンドは、MyCompany キーを作成します。New-Item コマンドレットの UseTransaction パ ラメーターを使用して、コマンドをアクティブなトランザクションに参加させています。 new-item MyCompany -UseTransaction このコマンドは、新しいキーを表すオブジェクトを返します。ただし、コマンドはトランザクションに 参加しているので、この時点では、レジストリは変更されません。 Hive: HKEY_CURRENT_USER\Software SKC VC Name Property --- -- ---- -------- 0 0 MyCompany {} トランザクションをコミットするには、Complete-Transaction コマンドレットを使用します。 これはアクティブなトランザクションに常に作用するので、特定のトランザクションを指定することはできません。 complete-transaction したがって、MyCompany キーはレジストリに追加されます。 dir m* Hive: HKEY_CURRENT_USER\software SKC VC Name Property --- -- ---- -------- 83 1 Microsoft {(default)} 0 0 MyCompany {} 例 2: トランザクションのロールバック トランザクションを作成するには、Start-Transaction コマンドレットを使用します。次のコマンド は、既定の設定でトランザクションを開始します。 start-transaction 次のコマンドは、MyOtherCompany キーを作成します。New-Item コマンドレットの UseTransaction パラメーターを使用して、コマンドをアクティブなトランザクションに参加させてい ます。 new-item MyOtherCompany -UseTransaction このコマンドは、新しいキーを表すオブジェクトを返します。ただし、コマンドはトランザクションに 参加しているので、この時点ではレジストリはまだ変更されません。 Hive: HKEY_CURRENT_USER\Software SKC VC Name Property --- -- ---- -------- 0 0 MyOtherCompany {} トランザクションをロールバックするには、Undo-Transaction コマンドレットを使用します。 これはアクティブなトランザクションに常に作用するので、特定のトランザクションを指定することはできません。 Undo-transaction 結果的に、MyOtherCompany キーはレジストリに追加されません。 dir m* Hive: HKEY_CURRENT_USER\software SKC VC Name Property --- -- ---- -------- 83 1 Microsoft {(default)} 0 0 MyCompany {} 例 3: トランザクションのプレビュー 通常、トランザクションには、データの変更を伴うコマンドが使用されます。しかし、トランザクションの 内部のデータを取得できるという意味で、データを取得するコマンドも有効活用できます。これにより、 トランザクションをコミットすることによって行われる変更をプレビューすることができます。 次の例では、Get-ChildItem コマンド (エイリアスは "dir") を使用して、トランザクションに含 まれる変更をプレビューします。 次のコマンドはトランザクションを開始します。 start-transaction 次のコマンドでは、New-ItemProperty コマンドレットを使用して、MyKey レジストリ エントリを MyCompany キーに追加します。このコマンドは UseTransaction パラメーターを使用して、コマン ドをトランザクションに含めます。 new-itemproperty -path MyCompany -Name MyKey -value 123 -UseTransaction このコマンドは、新しいレジストリ エントリを表すオブジェクトを返しますが、レジストリ エントリ は変更されません。 MyKey ----- 123 現在レジストリにある項目を取得するには、Get-ChildItem コマンド ("dir") を UseTransaction パラメーターなしで使用します。"M" で始まる項目を取得するコマンドを次に示し ます。 dir m* 次の結果から、MyCompany キーにはまだエントリが追加されていないことがわかります。 Hive: HKEY_CURRENT_USER\Software SKC VC Name Property --- -- ---- -------- 83 1 Microsoft {(default)} 0 0 MyCompany {} トランザクションをコミットした場合の結果をプレビューするには、Get-ChildItem ("dir") コマ ンドに UseTransaction パラメーターを付けて入力します。このコマンドによって、トランザクショ ン内のデータを確認できます。 dir m* -useTransaction 次の結果からは、トランザクションがコミットされた場合、MyKey エントリが MyCompany キーに追 加されることがわかります。 Hive: HKEY_CURRENT_USER\Software SKC VC Name Property --- -- ---- -------- 83 1 Microsoft {(default)} 0 1 MyCompany {MyKey} 例 4: トランザクション コマンドと非トランザクション コマンドの組み合わせ トランザクションの途中で、非トランザクション コマンドを入力することができます。非トランザクシ ョン コマンドは、データに対して直ちに作用しますが、トランザクションには影響しません。 次のコマンドは、HKCU:\Software レジストリ キーでトランザクションを開始します。 start-transaction 次の 3 つのコマンドは、New-Item コマンドレットを使用して、レジストリにキーを追加していま す。1 つ目と 3 つ目のコマンドは、UseTransaction パラメーターを使用して、コマンドをトランザ クションに参加させます。2 つ目のコマンドでは、このパラメーターが省略されています。2 つ目のコマ ンドはトランザクションに参加していないので、変更内容は直ちに反映されます。 new-item MyCompany1 -UseTransaction new-item MyCompany2 new-item MyCompany3 -UseTransaction レジストリの現在の状態を表示するには、Get-ChildItem ("dir") コマンドを UseTransaction パラメーターなしで使用します。次のコマンドは、"M" で始まる項目を取得します。 dir m* この結果から、MyCompany2 キーはレジストリに追加されていますが、トランザクションに参加していな い MyCompany1 キーと MyCompany3 キーは追加されていないことがわかります。 Hive: HKEY_CURRENT_USER\Software SKC VC Name Property --- -- ---- -------- 83 1 Microsoft {(default)} 0 0 MyCompany2 {} 次のコマンドはトランザクションをコミットします。 complete-transaction これで、トランザクション中に追加されたキーが、レジストリに反映されました。 dir m* Hive: HKEY_CURRENT_USER\Software SKC VC Name Property --- -- ---- -------- 83 1 Microsoft {(default)} 0 0 MyCompany1 {} 0 0 MyCompany2 {} 0 0 MyCompany3 {} 例 5: 自動ロールバックの使用 トランザクション内のコマンドで何かのエラーが発生した場合、トランザクションは自動的にロールバックされます。 この既定の動作は、トランザクションを実行するスクリプトを想定して設計されました。一般に、 スクリプトは十分なテストを重ね、エラー処理ロジックを組み込んで作成されます。エラーの発生は想定外であり、 万一、発生した場合は、トランザクションの終了をもって対処する必要があります。 まず、HKCU:\Software レジストリ キーでトランザクションを開始します。 start-transaction 次のコマンドは、New-Item コマンドレットを使用して、MyCompany キーをレジストリに追加しま す。このコマンドでは、UseTransaction パラメーター (エイリアスは "usetx") を使用して、コマ ンドをトランザクションに参加させます。 New-Item MyCompany -UseTX MyCompany キーは、既にレジストリに存在するので、コマンドは失敗し、トランザクションはロールバ ックされます。 New-Item : このパスにキーが既に存在しています 行:1 文字:9 + new-item <<<< MyCompany -usetx Get-Transaction コマンドを実行すると、トランザクションがロールバックされたこと、および、 SubscriberCount が 0 であることを確認できます。 RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 0 RolledBack 例 6: ロールバック設定の変更 トランザクションのエラーをもう少し寛容に扱う必要がある場合は、Start-Transaction の RollbackPreference パラメーターで設定を変更します。 次のコマンドは、ロールバック設定を "Never" にしてトランザクションを開始します。 start-transaction -rollbackpreference Never この場合、コマンドでエラーが発生しても、トランザクションは自動的にはロールバックされません。 New-Item MyCompany -UseTX New-Item : このパスにキーが既に存在しています 行:1 文字:9 + new-item <<<< MyCompany -usetx トランザクションは依然としてアクティブな状態であるので、同じトランザクション内でコマンドを再度実行することができます。 New-Item MyOtherCompany -UseTX 例 7: USE-TRANSACTION コマンドレットの使用 Use-Transaction コマンドレットでは、トランザクションに対応した Microsoft .NET Framework のオブジェクトを直接スクリプトで処理できます。Use-Transaction には、スクリプト ブロックを渡すことができます。スクリプト ブロックに含めることができるのは、トランザクション対応の .NET Framework オブジェクト (Microsoft.PowerShell.Commands.Management.TransactedString クラスのインスタンスなど) を使用したコマンドと式だけです。 次のコマンドはトランザクションを開始します。 start-transaction 次の New-Object コマンドは、TransactedString クラスのインスタンスを作成し、$t 変数に保 存します。 $t = New-Object Microsoft.PowerShell.Commands.Management.TransactedString 次のコマンドは、TransactedString オブジェクトの Append メソッドを使用して、文字列にテキス トを追加します。このコマンドはトランザクションの一部ではないので、変更内容は直ちに反映されます。 $t.append("Windows") 次のコマンドは、同じ Append メソッドを使用してテキストを追加します。ただし、今度は、トランザ クションの中でテキストを追加します。コマンドが中かっこで囲まれ、Use-Transaction の ScriptBlock パラメーターの値として設定されています。UseTransaction のパラメーター (UseTx) は必須です。 use-transaction {$t.append(" PowerShell")} -usetx $t 内のトランザクション処理済みの文字列について、現在の内容を確認するには、 TransactedString オブジェクトの ToString メソッドを使用します。 $t.tostring() 出力結果を見ると、トランザクションの外で行われた変更しか反映されていないことがわかります。 Windows $t 内のトランザクション処理済みの文字列について、トランザクション内から現在の内容を確認するに は、この式を Use-Transaction コマンドに埋め込むようにします。 use-transaction {$s.tostring()} -usetx 出力結果として、トランザクションを反映した結果が得られます。 Windows PowerShell 次のコマンドはトランザクションをコミットします。 complete-transaction 最終的な文字列を確認するには、次のように入力します。 $t.tostring() Windows PowerShell 例 8: マルチサブスクライバー トランザクションの管理 既存のトランザクションの進行中に別のトランザクションを開始した場合、既定では、新しいトランザクションは 開始されません。代わりに、現在のトランザクションにサブスクライバーが追加されます。 ここでは、マルチサブスクライバー トランザクションを表示したり管理したりする例を紹介します。 まず、HKCU:\Software キーでトランザクションを開始します。 start-transaction 次に、Get-Transaction コマンドを使用してアクティブなトランザクションを取得します。 get-transaction アクティブなトランザクションを表すオブジェクトが表示されます。 RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 1 Active 次のコマンドは、MyCompany キーをレジストリに追加します。このコマンドは UseTransaction パラメーターを使用して、コマンドをトランザクションに含めます。 new-item MyCompany -UseTransaction 次のコマンドでは、Start-Transaction コマンドを使用して、トランザクションを開始します。ここ では、コマンド プロンプトから入力していますが、どちらかと言えば、トランザクションを含んだスク リプトを実行するときによく用いる手法です。 start-transaction Get-Transaction コマンドを実行すると、トランザクション オブジェクトのサブスクライバー数が インクリメントされていることがわかります。現在の値は 2 です。 RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 2 Active 次のコマンドでは、New-ItemProperty コマンドレットを使用して、MyKey レジストリ エントリを MyCompany キーに追加します。このコマンドは UseTransaction パラメーターを使用して、コマン ドをトランザクションに含めます。 new-itemproperty -path MyCompany -name MyKey -UseTransaction MyCompany というキーは、レジストリに存在しません。それにもかかわらず、このコマンドが成功する のは、2 つのコマンドが、同じトランザクションに参加しているためです。 次のコマンドはトランザクションをコミットします。ここで仮にトランザクションをロールバックした場合、 すべてのサブスクライバーについて、トランザクションがロールバックされます。 complete-transaction Get-Transaction コマンドを実行すると、トランザクション オブジェクトのサブスクライバー数が 1 になってもなお、Status の値が (Committed ではなく) Active であることがわかります。 RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 1 Active トランザクションのコミットを完了するには、再度 Complete-Transaction コマンドを入力しま す。マルチサブスクライバー トランザクションをコミットするには、各 Start-Transaction コマン ドに対して Complete-Transaction コマンドを入力する必要があります。 complete-transaction もう一度 Get-Transaction コマンドを実行すると、トランザクションがコミットされています。 RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 0 Committed 例 9: 別トランザクションの管理 既存のトランザクションの進行中に別のトランザクションを開始する場合、Start-Transaction の Independent パラメーターを使用することで、元のトランザクションとは異なる別のトランザクショ ンとして開始することができます。 このとき、Start-Transaction によって、新しいトランザクション オブジェクトが作成され、その 新しいトランザクションがアクティブなトランザクションになります。 まず、HKCU:\Software キーでトランザクションを開始します。 start-transaction 次に、Get-Transaction コマンドを使用してアクティブなトランザクションを取得します。 get-transaction アクティブなトランザクションを表すオブジェクトが表示されます。 RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 1 Active 次のコマンドは、トランザクション処理として、MyCompany レジストリ キーを追加します。 UseTransaction のパラメーター (UseTx) を使用して、コマンドをアクティブなトランザクションに 参加させています。 new-item MyCompany -usetx 次のコマンドは、新しいトランザクションを開始します。アクティブなトランザクションのサブスクライバーではなく、 新しいトランザクションであることを伝えるために、Independent パラメーターが指定されています。 start-transaction -independent 独立した別のトランザクションを作成すると、新しい (最後に作成された) トランザクション オブジェ クトがアクティブなトランザクションになります。Get-Transaction コマンドを使用して、アクティ ブなトランザクションを取得できます。 get-transaction トランザクションの SubscriberCount が 1 であることに注意してください。これは、まったく新し いトランザクションであって、他にサブスクライバーは存在しないことを意味します。 RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 1 Active 元のトランザクションを管理するためには、新しいトランザクションをコミットするか、 ロールバックして完了する必要があります。 次のコマンドは、MyOtherCompany キーをレジストリに追加します。UseTransaction の パラメーター (UseTx) を使用して、コマンドをアクティブなトランザクション に参加させています。 new-item MyOtherCompany -usetx 今度は、トランザクションをロールバックします。仮に 2 つのサブスクライバーを持ったトランザクシ ョンが 1 つあるとき、そのトランザクションをロールバックすると、その 2 つのサブスクライバーの トランザクション全体がロールバックされます。 しかし、これらのトランザクションは互いに独立しているので、新しい方のトランザクションをロールバックすると、 レジストリの変更が取り消され、元のトランザクションがアクティブになります。 undo-transaction Get-Transaction コマンドを実行すると、そのセッションで、元のトランザクションがアクティブな ままになっていることを確認できます。 get-transaction RollbackPreference SubscriberCount Status ------------------ --------------- ------ Error 1 Active 次のコマンドは、アクティブなトランザクションをコミットします。 complete-transaction Get-ChildItem コマンドを実行すると、レジストリが変更されていることを確認できます。 dir m* Hive: HKEY_CURRENT_USER\Software SKC VC Name Property --- -- ---- -------- 83 1 Microsoft {(default)} 0 0 MyCompany {} 関連項目 Start-Transaction Get-Transaction Complete-Transaction Undo-Transaction Use-Transaction レジストリ (プロバイダー) about_Providers Get-PSProvider Get-ChildItem