Transactions describe a system's ability to support tentative or multi-step changes. When you make changes within the context of a transaction, the system provides four main guarantees:
Isolation: To observers not participating in the transaction, the commands inside the transaction have not impacted the system.
Atomicity: Once you decide to finalize (commit) a transaction, either all of the changes take effect, or none of them do.
Consistency: Errors caused during a transaction that would cause an inconsistent system state are dealt with in order to bring the system back to a consistent state.
Durability: Once the system has informed you of the transaction's successful completion, you can be certain that the changes are permanent.
As a real-world example of a transaction, consider a money transfer between two bank accounts. This might happen in two stages: subtract the money from the first account, and then add the money to the second account. In this situation, you have the exact same goals for robustness and correctness:
Might be worth including a non-technical example of a transaction eg a monetary transfer between bank accounts and link it to the 4 guarantees listed above
Isolation: While the money transfer is taking place (but has not yet completed), the balance of both bank accounts appears unchanged.
Atomicity: At some point in the process, it's possible that we've subtracted the money from the first account but haven't added it yet to the second account. When we process the money transfer, it's critical that the system never shows this intermediate state. Either all of the changes take effect, or none of them do.
Consistency: If an error occurs during the money transfer, the system takes corrective action to ensure that it is not left in an intermediate state. Perhaps it accounts for a lack of funds by adding an overdraft charge, or by abandoning the entire money transfer altogether. It should not, for example, have taken the funds from one account without depositing them into the second account.
Durability: Once the money transfer completes, you don't have to worry about a system error undoing all or part of it.
While normally a developer topic, PowerShell exposes transactions as an end-user concept, opening a great deal of potential for consistent system management.
To start a transaction, call the
Start-Transaction cmdlet. To use a cmdlet that supports
transactions, specify the –UseTransaction parameter.
Being explicit about this parameter is crucial, as many cmdlets that
support transactions can work equally well without one. Because of that,
PowerShell only lets the cmdlet participate in the transaction when you
supply this parameter.
In Windows Vista and later, PowerShell’s registry provider supports transactions as a first-class concept. You can see this in action in the section called “Safely Combine Related Registry Modifications”,
PS > Set-Location HKCU:
PS > Start-Transaction
PS > mkdir TempKey -UseTransaction
Hive: HKEY_CURRENT_USER
SKC VC Name Property
--- -- ---- --------
0 0 TempKey {}
PS > New-Item TempKey\TempKey2 -UseTransaction
Hive: HKEY_CURRENT_USER\TempKey
SKC VC Name Property
--- -- ---- --------
0 0 TempKey2 {}
PS > Get-ChildItem TempKey
Get-ChildItem : Cannot find path 'HKEY_CURRENT_USER\TempKey' because it do
es not exist.
PS > Complete-Transaction
PS > Get-ChildItem TempKey
Hive: HKEY_CURRENT_USER\TempKey
SKC VC Name Property
--- -- ---- --------
0 0 TempKey2 {}Once you have
completed the transactional work, call the
Complete-Transaction cmdlet to make it final, or the
Undo-Transaction cmdlet to discard the changes. While
you may now be tempted to experiment with transactions on other providers
(for example, the filesystem), be aware that only the registry provider
currently supports them.
You want to experiment with PowerShell's transactions support, but don't want to use the Registry Provider as your playground.
suport --> support
Use PowerShell's
System.Management.Automation.TransactedString object
along with the Use-Transaction cmdlet to experiment
with a string, rather than registry keys:
Do we get any information on other .NET classes that support transactions
I thought about that, but it seems a bit too much for most to chew. Our goal was not to introduce transacted .NET scripting to the masses, but to support transacted scripting for developers that could previously only do this through compiled .NET languages.
PS > Start-Transaction
Suggestion [1,Transactions]: Once a transaction is started, only commands that
get called with the -UseTransaction flag become part of that transaction.
PS >
PS > $transactedString = New-Object Microsoft.PowerShell.Commands.Management.Tra
nsactedString
PS > $transactedString.Append("Hello ")
PS >
PS > Use-Transaction -UseTransaction { $transactedString.Append("World") }
Suggestion [2,Transactions]: The Use-Transaction cmdlet is intended for script
ing of transaction-enabled .NET objects. Its ScriptBlock should contain nothin
g else.
PS >
PS > $transactedString.ToString()
Hello
PS >
PS > Complete-Transaction
PS >
PS > $transactedString.ToString()
Hello World
PS > PowerShell's transaction support builds on
four core cmdlets: Start-Transaction,
Use-Transaction,
Complete-Transaction, and
Undo-Transaction.
The Start-Transaction
begins a transaction, creating a context where changes are visible to
commands within the transaction, but not outside of it. For the most
part, after starting a transaction, you'll apply commands to that
transaction by adding the -UseTransaction to a cmdlet
that supports it. For example, when a PowerShell provider supports
transactions, all of PowerShell's core cmdlets
(Get-ChildItem, Remove-Item, etc),
let you specify the -UseTransaction parameter for
actions against that provider.
The Use-Transaction cmdlet
is slightly different. While it still requires the
-UseTransaction parameter to apply its script block
to the current transaction, its sole purpose is to let you script
against .NET objects that support transactions themselves. Since they
have no way to supply a -UseTransaction parameter,
PowerShell offers this generic cmdlet for any type of transactional .NET
scripting.
do ADO.NET transactions work with this method?
Other transaction-enabled cmdlets should
not be called within the Use-Transaction script
block. You'll still need to provide the
-UseTransaction parameter to the cmdlet being
called, and there's a chance that they might cause instability with
your PowerShell-wide transactions.
To give users an opportunity to play with something a little
less risky than the Windows Registry, PowerShell includes the
Microsoft.PowerShell.Commands.Management.TransactedString
class. This class acts like you'd expect any transacted command to act,
and lets you become familiar with how the rest of PowerShell's
transaction cmdlets work together. Since this is a .NET object, it must
be called from within the script block of the
Use-Transaction cmdlet.
Finally, when you are finished performing
tasks for the current transaction, call either the
Complete-Transaction or
Undo-Transaction cmdlets. As compared to the
solution, here's an example session where the
Undo-Transaction cmdlet lets you discard changes made
during the transaction:
PS > Start-Transaction
Suggestion [1,Transactions]: Once a transaction is started, only commands that
get called with the -UseTransaction flag become part of that transaction.
PS >
PS > $transactedString = New-Object Microsoft.PowerShell.Commands.Management.Tra
nsactedString
PS > $transactedString.Append("Hello ")
PS >
PS > Use-Transaction -UseTransaction { $transactedString.Append("World") }
Suggestion [2,Transactions]: The Use-Transaction cmdlet is intended for script
ing of transaction-enabled .NET objects. Its ScriptBlock should contain nothin
g else.
PS >
PS > $transactedString.ToString()
Hello
PS >
PS > Undo-Transaction
PS >
PS > $transactedString.ToString()
HelloSuggestion [2,Transactions]: The Use-Transaction cmdlet is intended for script ing of transaction-enabled .NET objects. Its ScriptBlock should contain nothin g else. PS> PS>$transactedString.ToString() Hello PS> PS>Undo-Transaction PS> PS>$transactedString.ToString() Hello ( A little obscure perhaps ? )
For more information about transactions in the Windows Registry, see the section called “Safely Combine Related Registry Modifications”.
You want to change how PowerShell responds to errors during the execution of a transacted cmdlet.
Use the -RollbackPreference
parameter of the Start-Transaction cmdlet to control
what type of error will cause PowerShell to automatically undo your
transaction:
HKCU:\ >Start-Transaction
HKCU:\ >New-Item Foo -UseTransaction
Hive: HKEY_CURRENT_USER
SKC VC Name Property
--- -- ---- --------
0 0 Foo {}
HKCU:\ >Copy IDoNotExist Foo -UseTransaction
Copy-Item : Cannot find path 'HKCU:\IDoNotExist' because it does not exist.
HKCU:\ >Complete-Transaction
Complete-Transaction : Cannot commit transaction. The transaction has been ro
lled back or has timed out.
HKCU:\ >Start-Transaction -RollbackPreference TerminatingError
Hive: HKEY_CURRENT_USER
SKC VC Name Property
--- -- ---- --------
0 0 Foo {}
HKCU:\ >Copy IDoNotExist Foo -UseTransaction
Copy-Item : Cannot find path 'HKCU:\IDoNotExist' because it does not exist.
HKCU:\ >Complete-Transaction
HKCU:\ >Get-Item Foo
Hive: HKEY_CURRENT_USER
SKC VC Name Property
--- -- ---- --------
0 0 Foo {}Errors in scripts are an extremely frequent cause of system inconsistency. If a script incorrectly assumes the existence of a registry key or other system state, this type of error tends to waterfall through the entire script. As the script continues, some of the operations succeed, while others fail. When the script completes, you're in a difficult situation in not knowing exactly what portions of the script worked correctly.
Sometimes, running the script again will magically make the problems go away. Unfortunately, it's just as common to have a painstaking manual cleanup effort facing you.
Addressing these consistency issues is one of the primary goals of system transactions.
When PowerShell creates a new transaction, it undoes (rolls back) your transaction for any error it encounters that is operating in the context of that transaction. When PowerShell rolls back your transaction, the system impact is clear: no part of your transaction was made permanent, so your system is still entirely consistent.
Some situations are simply too volatile to be
able to depend on this rigid interpretation of consistency, though, so
PowerShell offers the -RollbackPreference parameter
on the Start-Transaction to let you configure how it
should respond to errors:
Some situations are simply to volatile ( too )
Error: PowerShell
rolls back your transaction when any error occurs
TerminatingError:
PowerShell only rolls back your transaction when a terminating
error occurs
Never: PowerShell
never automatically rolls back your transaction in response to
errors
For more information about PowerShell's error handling and error levels, see Chapter 15, Tracing and Error Management.
2 comments
Reviewing
Could be good to include note that transactions are available from Vista OS.
Add a comment