about_Transactions

简短说明

介绍如何在 PowerShell 中管理事务处理操作。

长说明

从 PowerShell 2.0 开始,PowerShell 支持事务。 此功能使你能够启动事务,指示哪些命令是事务的一部分,以及提交或回滚事务。

在 PowerShell 中,事务是作为逻辑单元进行管理的一个或多个命令。 可以完成事务(“提交”),这会更改受事务影响的数据。 或者,事务可以完全撤消(“回滚”),以便事务不会更改受影响的数据。

由于事务中的命令作为一个单元进行管理,因此所有命令不是全部提交就是全部回滚。

事务广泛应用于数据处理,尤其是数据库操作和财务事务。 当一组命令最糟糕的情况不是它们都失败,而是某些命令成功,而其他命令失败时,通常使用事务,使系统处于难以修复的损坏、false 或不可解释的状态。

事务 cmdlet

PowerShell 包含多个用于管理事务的 cmdlet。

  • Start-Transaction:启动新事务。
  • Use-Transaction:向事务添加命令或表达式。 该命令必须使用支持事务的对象。
  • Undo-Transaction:回滚事务,以便事务不更改任何数据。
  • Complete-Transaction:提交事务。 会更改受事务影响的数据。
  • Get-Transaction:获取有关活动事务的信息。

如需事务 cmdlet 的列表,请键入:

Get-Command *transaction

如需有关 cmdlet 的详细信息,请键入:

Get-Help Use-Transaction -Detailed

已启用事务的元素

若要参与事务,cmdlet 和提供程序都必须支持事务。 此功能内置于受事务影响的对象中。

PowerShell 注册表提供程序支持 Windows 中的事务。 TransactedString 对象适用于运行 PowerShell 的任何操作系统。

其他 PowerShell 提供程序可以支持事务。 若要在支持事务的会话中查找 PowerShell 提供程序,请使用以下命令在提供程序的 Capabilities 属性中查找事务值:

Get-PSProvider | Where-Object {$_.Capabilities -like "*transactions*"}

有关提供程序的详细信息,请参阅提供程序的帮助。 若要获取提供程序帮助,请键入:

Get-Help <provider-name>

例如,若要获取有关 Registr 提供程序的帮助,请键入:

Get-Help Registry

UseTransaction 参数

可支持事务的 Cmdlet 具有 UseTransaction 参数。 此参数包含活动事务中的命令。 可以使用完整参数名称或其别名 usetx

仅当会话包含活动事务时才能使用该参数。 如果没有活动事务时输入具有 UseTransaction 参数的命令,该命令将失败。

若要使用 UseTransaction 参数查找 cmdlet,请键入:

Get-Help * -Parameter UseTransaction

在 PowerShell 核心中,设计用于处理 PowerShell 提供程序的所有 cmdlet 都支持事务。 因此,可以使用提供程序 cmdlet 来管理事务。

有关 PowerShell 提供程序的详细信息,请参阅 about_Providers

事务对象

事务由事务对象 System.Management.Automation.Transaction 在 PowerShell 中表示。

对象具有以下属性:

  • RollbackPreference:包含当前事务的回滚首选项集。 在用于 Start-Transaction 启动事务时,可以设置回滚首选项。

    回滚首选项确定事务自动回滚的条件。 有效值为 ErrorTerminatingErrorNever。 默认值为 Error

  • 状态:包含事务的当前状态。 有效值为 ActiveCommittedRolledBack

  • SubscriberCount:包含事务的订阅服务器数。 如果在另一个事务正在进行时启动另一个事务时,就会将订阅者添加到事务。 当订阅者提交事务时,订阅者计数会减少。

活动事务

在 PowerShell 中,一次只有一个事务处于活动状态,并且你只能管理活动事务。 在同一会话中可以同时进行多个事务,但只有最近启动的事务处于活动状态。

因此,在使用事务 cmdlet 时,不能指定特定事务。 命令始终适用于活动事务。

这在 cmdlet 的行为 Get-Transaction 中最为明显。 输入 Get-Transaction 命令时, Get-Transaction 始终只获取一个事务对象。 该对象是代表活动事务的对象。

若要管理其他事务,必须首先通过提交或回滚来完成活动事务。 执行此操作时,之前的事务会自动激活。 事务在启动顺序相反的情况下变为活动状态,以便最近启动的事务始终处于活动状态。

订阅服务器和独立事务

如果在另一个事务正在进行时启动事务,则默认情况下,PowerShell 不会启动新事务。 在这种情况下,它会向当前事务添加一个“订阅者”。

当事务有多个订阅服务器时,任何时间点的单个 Undo-Transaction 命令都会回滚所有订阅服务器的整个事务。 但是,若要提交事务,必须为每个订阅者输入一个 Complete-Transaction 命令。

若要查找事务的订阅者数量,请检查事务对象的 SubscriberCount 属性。 例如,以下命令使用 Get-Transaction cmdlet 获取活动事务的 SubscriberCount 属性的值:

(Get-Transaction).SubscriberCount

添加订阅者是默认行为,因为在另一个事务正在进行时启动的大多数事务都与原始事务相关。 在典型模型中,包含事务的脚本将调用包含其自身事务的帮助器脚本。 由于事务是相关的,因此应将其作为一个单元回滚或提交。

但是,可以使用 cmdlet 的独立参数启动独立于当前事务的 Start-Transaction 事务。

启动独立事务时, Start-Transaction 创建新的事务对象,新事务将成为活动事务。 可以提交或回滚独立事务,而不影响原始事务。

当独立事务完成(提交或回滚)时,原始事务再次变为活动事务。

更改数据

使用事务更改数据时,在提交事务之前,受事务影响的数据不会更改。 但是,不是事务的一部分的命令可以更改相同的数据。

使用事务管理共享数据时,请记住这一点。 通常,数据库具有在处理数据时锁定数据的机制,以防止其他用户以及其他命令、脚本和函数更改数据。

但是,锁定是数据库的一项功能。 它与事务无关。 如果你正在支持事务的文件系统或其他数据存储中工作,则可以在事务处理过程中更改数据。

示例

本部分的示例使用 PowerShell 注册表提供程序并假设你熟悉该提供程序。 有关注册表提供程序的信息,请键入 Get-Help Registry

示例 1:提交事务

若要创建事务,请使用 Start-Transaction cmdlet。 以下命令使用默认设置启动事务。

Start-Transaction

若要在事务中包含命令,请使用 cmdlet 的 UseTransaction 参数。 默认情况下,事务中不包含命令,

例如,在驱动器的软件密钥 HKCU: 中设置当前位置的以下命令不包括在事务中。

cd HKCU:\Software

以下命令创建 MyCompany 密钥,它使用 参数将命令包含在活动事务中。

New-Item MyCompany -UseTransaction

该命令返回一个表示新键的对象,但由于该命令是事务的一部分,因此注册表尚未更改。

Hive: HKEY_CURRENT_USER\Software

SKC  VC Name                           Property
---  -- ----                           --------
  0   0 MyCompany                      {}

若要提交事务,请使用 Complete-Transaction cmdlet。 因为它始终影响活动事务,因此无法指定事务。

Complete-Transaction

因此,密钥 MyCompany 将添加到注册表。

dir m*
Hive: HKEY_CURRENT_USER\software

SKC  VC Name                           Property
---  -- ----                           --------
 83   1 Microsoft                      {(default)}
  0   0 MyCompany                      {}

示例 2:回滚事务

若要创建事务,请使用 Start-Transaction cmdlet。 以下命令使用默认设置启动事务。

Start-Transaction

以下命令创建 MyOtherCompany 密钥,它使用 cmdlet 的 New-Item UseTransaction 参数将命令包含在活动事务中。

New-Item MyOtherCompany -UseTransaction

该命令返回一个表示新键的对象,但由于该命令是事务的一部分,因此注册表尚未更改。

Hive: HKEY_CURRENT_USER\Software

SKC  VC Name                           Property
---  -- ----                           --------
  0   0 MyOtherCompany                 {}

若要回滚事务,请使用 Undo-Transaction cmdlet。 因为它始终影响活动事务,因此不指定事务。

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 cmdlet 将 MyKey 注册表项添加到 MyCompany 键。 该命令使用 UseTransaction 参数在事务中包含命令。

New-ItemProperty -Path MyCompany -Name MyKey -Value 123 -UseTransaction

该命令返回一个表示新注册表项的对象,但注册表项不会更改。

MyKey
-----
123

若要获取当前在注册表中的项,请使用 Get-ChildItem 不使用 UseTransaction 参数的命令(dir)。 以下命令获取以“M”开头的项。

dir m*

结果显示尚未向键添加 MyCompany 任何条目。

Hive: HKEY_CURRENT_USER\Software

SKC  VC Name                           Property
---  -- ----                           --------
 83   1 Microsoft                      {(default)}
  0   0 MyCompany                      {}

若要预览提交事务的效果,请使用 UseTransaction 参数输入一个 Get-ChildItemdir) 命令。 该命令提供事务中数据的视图。

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

接下来的三个命令使用 New-Item cmdlet 将密钥添加到注册表。 第一个和第三个命令使用 UseTransaction 参数将命令包含在事务中。 第二个命令省略了参数。 由于第二个命令未包含在事务中,因此会立即生效。

New-Item MyCompany1 -UseTransaction
New-Item MyCompany2
New-Item MyCompany3 -UseTransaction

若要查看注册表的当前状态,请使用 Get-ChildItem 不使用 UseTransaction 参数的 (dir) 命令。 此命令获取以 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 cmdlet 将 MyCompany 密钥添加到注册表。 该命令使用 UseTransaction 参数(别名为 usetx)将命令包含在事务中。

New-Item MyCompany -usetx

MyCompany由于注册表项已存在于注册表中,因此命令会失败,事务将回滚。

New-Item : A key at this path already exists
At line:1 char:9
+ New-Item <<<<  MyCompany -usetx

命令 Get-Transaction 确认事务已回滚,并且 SubscriberCount 为 0。

RollbackPreference   SubscriberCount   Status
------------------   ---------------   ------
Error                0                 RolledBack

示例 6:更改回滚首选项

如果希望事务更容错,可以使用 RollbackPreference 参数 Start-Transaction 来更改首选项。

以下命令启动具有回退首选项的 Never事务。

Start-Transaction -RollbackPreference Never

在这种情况下,当命令失败时,不会自动回滚事务。

New-Item MyCompany -usetx
New-Item : A key at this path already exists
At line:1 char:9
+ New-Item <<<<  MyCompany -usetx

由于事务仍然处于活动状态,因此你可以重新提交命令作为事务的一部分。

New-Item MyOtherCompany -usetx

示例 7:使用 Use-Transaction cmdlet

通过 Use-Transaction cmdlet,可以针对启用了事务的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 方法来添加文本,但它将文本添加为事务的一部分。 该命令括在大括号中,并设置为 ScriptBlock需要 UseTransaction 参数 (usetx)。

Use-Transaction {$t.Append(" PowerShell")} -usetx

若要查看事务处理字符串$t的当前内容,请使用 ToString TransactedString 对象的方法

$t.ToString()

输出显示只有非事务处理更改才会生效。

Windows

若要查看事务中事务处理字符串的当前内容,请从事务中嵌入表达式 Use-Transaction $t。

Use-Transaction {$t.ToString()} -usetx

输出显示事务视图。

PowerShell

以下命令提交事务。

Complete-Transaction

若要查看最终字符串:

$t.ToString()
PowerShell

示例 8:管理多订阅服务器事务

当另一个事务正在进行时启动事务时,PowerShell 默认情况下不会创建第二个事务。 在这种情况下,它会向当前事务添加一个订阅者。

此示例演示如何查看和管理多订阅者事务。

首先在密钥中 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 cmdlet 将 MyKey 注册表项添加到 MyCompany 键。 它使用 UseTransaction 参数在事务中包含命令。

New-ItemProperty -Path MyCompany -Name MyKey -UseTransaction

注册表中不存在 MyCompany 键,但此命令成功,因为两个命令是同一事务的一部分。

以下命令提交事务。 如果回滚了事务,则所有订阅者的事务都会回滚。

Complete-Transaction

命令 Get-Transaction 显示事务对象的订阅服务器计数为 1,但状态值仍为活动(未提交)。

RollbackPreference   SubscriberCount   Status
------------------   ---------------   ------
Error                1                 Active

若要完成提交事务,请输入第二个 Complete-Transaction 命令。 若要提交多订阅服务器事务,必须为每个Complete-Transaction命令输入一个Start-Transaction命令。

Complete-Transaction

另一个 Get-Transaction 命令显示事务已提交。

RollbackPreference   SubscriberCount   Status
------------------   ---------------   ------
Error                0                 Committed

示例 9:管理独立事务

当另一个事务正在进行时启动事务时,可以使用 独立 参数 Start-Transaction 使新事务独立于原始事务。

执行此操作时, Start-Transaction 创建一个新的事务对象,并将新事务设置为活动事务。

首先在密钥中 HKCU:\Software 启动事务。

Start-Transaction

以下命令使用 Get-Transaction 命令获取活动事务。

Get-Transaction

结果显示代表活动事务的对象。

RollbackPreference   SubscriberCount   Status
------------------   ---------------   ------
Error                1                 Active

以下命令将 MyCompany 注册表项添加为事务的一部分。 它使用 UseTransaction 参数 (usetx) 将命令包含在活动事务中。

New-Item MyCompany -use

以下命令启动新事务。 该命令使用 Independent 参数指示此事务不是活动事务的订阅服务器。

Start-Transaction -Independent

创建独立事务时,新的(最近创建的)事务将变成活动事务。 可以使用 Get-Transaction 命令获取活动事务。

Get-Transaction

请注意,该事务的 SubscriberCount 为 1(表示没有其他订阅者),并且该事务是新的。

RollbackPreference   SubscriberCount   Status
------------------   ---------------   ------
Error                1                 Active

必须先完成新事务(提交或回滚),然后才能管理原始事务。

以下命令将 MyOtherCompany 项添加到注册表中。 它使用 UseTransaction 参数 (usetx) 将命令包含在活动事务中。

New-Item MyOtherCompany -usetx

现在回滚事务。 如果单个事务有两个订阅者,则回滚该事务会回滚所有订阅者的整个事务。

但是,由于这些事务是独立的,回滚最新事务会取消注册表更改,并使原始事务变成活动事务。

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

另请参阅