about_Transactions
简短说明
介绍如何在 PowerShell 中管理事务处理操作。
长说明
从 PowerShell 2.0 开始,PowerShell 支持事务。 此功能使你能够启动事务,指示哪些命令是事务的一部分,以及提交或回滚事务。
关于事务
在 PowerShell 中,事务是作为逻辑单元进行管理的一个或多个命令。 可以完成事务(“提交”),这会更改受事务影响的数据。 或者,可以完全撤消事务(“回滚”),使事务不会更改受影响的数据。
由于事务中的命令作为一个单元进行管理,因此所有命令不是全部提交就是全部回滚。
事务广泛应用于数据处理,尤其是数据库操作和财务事务。 事务的最常用场景是当一组命令的最坏结果不是全部失败,而是某些命令成功而另一些命令失败,从而导致系统进入损坏、出错或难以修复的不可解释状态时。
事务 CMDLET
PowerShell 包含多个用于管理事务的 cmdlet。
- Start-Transaction:启动新事务。
- Use-Transaction:向事务添加命令或表达式。 该命令必须使用支持事务的对象。
- 撤消事务:回滚事务,使事务不会更改任何数据。
- Complete-Transaction:提交事务。 会更改受事务影响的数据。
- Get-Transaction:获取有关活动事务的信息。
如需事务 cmdlet 的列表,请键入:
get-command *transaction
如需有关 cmdlet 的详细信息,请键入:
get-help use-transaction -detailed
支持事务的元素
若要参与事务,cmdlet 和提供程序都必须支持事务。 此功能内置于受事务影响的对象中。
PowerShell 注册表提供程序支持 Windows Vista 中的事务。 TransactedString 对象 (Microsoft.PowerShell.Commands.Management.TransactedString) 适用于运行 PowerShell 的任何操作系统。
其他 PowerShell 提供程序可以支持事务。 若要在会话中查找支持事务的 PowerShell 提供程序,请使用以下命令在提供程序的“功能”属性中查找“事务”值:
get-psprovider | where {$_.Capabilities -like "*transactions*"}
有关提供程序的详细信息,请参阅提供程序的帮助。 若要获取提供程序帮助,请键入:
get-help <provider-name>
例如,若要获取有关 Registr 提供程序的帮助,请键入:
get-help registry
事务参数
支持事务的 cmdlet 带有 UseTransaction 参数。 此参数包含活动事务中的命令。 可以使用完整参数名称或其别名“usetx”。
仅当会话包含活动事务时才能使用该参数。 如果在没有活动事务的情况下输入带有 UseTransaction 参数的命令,该命令将会失败。
若要查找带有 UseTransaction 参数的 cmdlet,请键入:
get-help * -parameter UseTransaction
在 PowerShell 核心中,所有设计为与 PowerShell 提供程序配合使用的 cmdlet 都支持事务。 因此,可以使用提供程序 cmdlet 来管理事务。
有关 PowerShell 提供程序的详细信息,请参阅 about_Providers。
事务对象
事务在 PowerShell 中由事务对象 System.Management.Automation.Transaction 表示。
对象具有以下属性:
RollbackPreference:包含针对当前事务设置的回滚首选项。 可以在使用 Start-Transaction 启动事务时设置回滚首选项。
回滚首选项确定事务自动回滚的条件。 有效值为 Error、TerminatingError 和 Never。 默认值为 Error。
Status:包含事务的当前状态。 有效值为 Active、Committed 和 RolledBack。
SubscriberCount:包含事务的订阅者数量。 如果在另一个事务正在进行时启动另一个事务时,就会将订阅者添加到事务。 当订阅者提交事务时,订阅者计数会减少。
活动事务
在 PowerShell 中,一次只有一个事务处于活动状态,并且你只能管理活动事务。 在同一会话中可以同时进行多个事务,但只有最近启动的事务处于活动状态。
因此,在使用事务 cmdlet 时无法指定特定的事务。 命令始终适用于活动事务。
这种情况在 Get-Transaction cmdlet 的行为中最为明显。 当你输入 Get-Transaction 命令时,Get-Transaction 始终仅获取一个事务对象。 该对象是代表活动事务的对象。
若要管理其他事务,必须首先通过提交或回滚来完成活动事务。 执行此操作时,之前的事务会自动激活。 事务按照与启动顺序相反的顺序变为活动状态,因此最近启动的事务始终处于活动状态。
订阅者和独立事务
如果在一个事务正在进行时启动另一个事务,则默认情况下,PowerShell 不会启动新事务。 在这种情况下,它会向当前事务添加一个“订阅者”。
当事务有多个订阅者时,在任何时候执行的单个 Undo-Transaction 命令都会为所有订阅者回滚整个事务。 但是,若要提交事务,必须为每个订阅者输入 Complete-Transaction 命令。
若要查找事务的订阅者数量,请检查事务对象的 SubscriberCount 属性。 例如,以下命令使用 Get-Transaction cmdlet 获取活动事务的 SubscriberCount 属性值:
(Get-Transaction).SubscriberCount
添加订阅者是默认行为,因为在另一个事务正在进行时启动的大多数事务都与原始事务相关。 在典型模型中,包含事务的脚本将调用包含其自身事务的帮助器脚本。 由于事务是相关的,因此应将其作为一个单元回滚或提交。
但是,可以使用 Start-Transaction cmdlet 的 Independent 参数来启动独立于当前事务的事务。
当你启动独立事务时,Start-Transaction 会创建新的事务对象,并且新事务将成为活动事务。 可以提交或回滚独立事务,而不影响原始事务。
当独立事务完成(提交或回滚)时,原始事务再次变为活动事务。
更改数据
使用事务更改数据时,受事务影响的数据在提交事务之前不会更改。 但是,相同数据可以通过不属于事务的一部分的命令来更改。
使用事务管理共享数据时,请记住这一点。 通常,数据库具有在处理数据时锁定数据的机制,以防止其他用户以及其他命令、脚本和函数更改数据。
但是,锁定是数据库的一项功能。 它与事务无关。 如果你正在支持事务的文件系统或其他数据存储中工作,则可以在事务处理过程中更改数据。
示例
本部分的示例使用 PowerShell 注册表提供程序并假设你熟悉该提供程序。 如需有关注册表提供程序的信息,请键入“get-helpregistry”。
示例 1:提交事务
若要创建事务,请使用 Start-Transaction cmdlet。 以下命令使用默认设置启动事务。
start-transaction
若要在事务中包含命令,请使用 cmdlet 的 UseTransaction 参数。 默认情况下,命令不会包含在事务中。
例如,以下命令(设置 HKCU: 驱动器的 Software 注册表项的当前位置)不会包含在事务中。
cd hkcu:\Software
以下命令(创建 MyCompany 注册表项)使用 New-Item cmdlet 的 UseTransaction 参数将该命令包含在活动事务中。
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 注册表项)使用 New-Item cmdlet 的 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
若要获取注册表中当前的项,请使用不带 UseTransaction 参数的 Get-ChildItem 命令 ("dir")。 以下命令获取以“M”开头的项。
dir m*
结果显示尚未将任何项添加到 MyCompany 项中。
Hive: HKEY_CURRENT_USER\Software
SKC VC Name Property
--- -- ---- --------
83 1 Microsoft {(default)}
0 0 MyCompany {}
若要预览提交事务的效果,请输入带有 UseTransaction 参数的 Get-ChildItem ("dir") 命令。 该命令提供事务中数据的视图。
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
若要查看注册表的当前状态,请使用不带 UseTransaction 参数的 Get-ChildItem ("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:更改回滚首选项
如果你希望事务具有更高的容错能力,可以使用 Start-Transaction 的 RollbackPreference 参数来更改首选项。
以下命令启动一个回滚首选项为“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 方法来添加文本,但它将文本添加为事务的一部分。 该命令括在大括号中,并设置为 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
输出显示事务视图。
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,但 Status 的值仍然是 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 -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 {}
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈