Chapter 07

Transactions

In This Chapter

*	Understanding transactions

*	Querying for packages based on transactions

*	Rolling back transactions

*	Saving old packages when upgrading

When packages depend on other packages, you may have to install multiple packages to add a single application. Some of the packages may install cleanly; others may not. But you have to install all of the packages to get the complete application. The designers of the RPM system understood this problem and added the concept of transactions to RPM.

This chapter covers transactions and how they can help you cleanly install a set of dependent packages. But transactions won’t solve all your problems. You still have to resolve conflicts and dependencies by using the techniques provided in the last three chapters.

Understanding Transactions

A transaction is a way to delimit a set of operations. All the operations can be undone, often called rolled back. Once rolled back, the system is back in the same state it was prior to the transaction. If all the operations succeed, though, the system will be in a new state. The key issue is that all of the operations must complete successfully, or you can roll back the entire transaction. The assumption is that if any of the operations fail, the system will be in an inconsistent or erroneous state. Transactions are a way to prevent that.

Transactions are common when working with databases, but they are just as important when working with packages.

Starting with RPM version 4.0.4, transactions and rollbacks became a workable part of any administrator's toolkit. With RPM, the rpm command sets up a transaction any time you attempt to install, remove, or upgrade more than one package. The rpm command automatically makes a transaction.

When do you need transactions?

Whenever you install or remove packages, the RPM system assigns a transaction and a transaction ID to the set of packages. You can then perform operations on the packages that share the same ID, including rolling back the transaction.

Note

Rollbacks work only for package upgrades with the 4.1 version of the RPM system, not package installs

The RPM system saves an image of the RPM package header for each package installed or removed. You can use this image, along with RPM transaction IDs, to back out of transactions should something go wrong when setting up your system.

The main advantage of transactions with RPM, though, is the fact that the rpm command automatically sets up a transaction for all the packages on each command line and does not perform the operation if any package fails. This ability to automatically set up transactions for each call to the rpm command eliminates many errors when working with packages.

Use a transaction when you need to be sure that a set of packages install properly.

Backing out of transactions

With RPM, backing out of a transaction involves two operations: rolling back the transaction and reinstalling the former packages to restore the previous system state. In the simplest case, the rpm command handles all the tasks for you. If you try to install, upgrade, or remove multiple packages and any package fails, the rpm command will restore the system state for you.

This automatic support for transactions is a great help to system administrators, but it only applies when you first install, upgrade, or remove the packages. If you have upgraded your system and later discover problems, then you can also use the --rollback option to roll the system back from a set of upgrades, in a limited set of circumstances.

Transactions with the rpm Command

To set up an RPM transaction, you don't have to do much. All you need to do is pass more than one RPM package on the rpm command line. For example, to set up a transaction for installing three packages, use a command like the following:

rpm -ihv package1.rpm package2.rpm package3.rpm

If any of the packages fail to install, the rpm command will not install any packages. All of the packages will be installed, or none.

This way, if you have a number of packages that together perform some function, such as an Integrated Development Environment (IDE), along with program-language compilers and other software-development tools, you can ensure that all get installed.

As an example, say you need to install the gnorpm package, which provides a graphical front end for the rpm command, and the rpmrebuild package, which allows you to create RPMs from already-installed packages.

Cross Reference

The gnorpm command is covered in Chapter 8. The rpmrebuild package is covered in the "Saving Old Packages" section in this chapter.

You can install these packages with a transaction by using the following command:

# rpm -ihv gnorpm-0.9-1.i386.rpm rpmrebuild-1.0-0.noarch.rpm

Preparing... ########################################### [100%]

package gnorpm-0.9-1 is already installed

The rpmrebuild package can be installed. (We know this since the rpm command did not issue an error about this package.) But because it was on the same command line as the gnorpm package, the transaction failed. No packages were installed.

To check that the rpmrebuild package was not installed (that is, to check that the transaction worked as expected), you can use the rpm –q command to see if the rpmrebuild package was installed or not. To do so, use a command like the following:

# rpm -q rpmrebuild

package rpmrebuild is not installed

This shows that the rpmrebuild package was not installed, even though the package could be installed on its own. To check that the package could be installed, you can use the --test option, as shown following:

# rpm -i --test rpmrebuild-1.0-0.noarch.rpm

#

This command shows that the rpmrebuild package would install successfully on its own. If there were problems, the rpm command would have issued an error message.

This example shows that when you try to install multiple packages with the rpm command, should any fail, the rpm command will not install any.

The rpm command works similarly for removing packages and upgrading packages. When removing packages, you’ll see an error like the following if any of the packages on the command line cannot be removed:

# rpm -e setup jikes-1.17

error: Failed dependencies:

setup is needed by (installed) basesystem-8.0-1

setup >= 2.0.3 is needed by (installed) initscripts-6.95-1

setup >= 2.5.4-1 is needed by (installed) filesystem-2.1.6-5

setup is needed by (installed) xinetd-2.3.7-2

setup is needed by (installed) dump-0.4b28-4

The setup package could not be removed because it had several capabilities needed by other packages. You can check that the jikes package was not removed by using the rpm –q command, even though it had no failed dependencies:

# rpm -q jikes

jikes-1.17-1

This package was not removed because it appeared as part of the same command that failed, so none of the operations were performed.

When upgrading, you will also see an error message if any of the package upgrades fail. For example:

# rpm -Uhv jikes-1.14-1.i386.rpm autoupdate-3.1.5-1.noarch.rpm

error: jikes-1.14-1.i386.rpm cannot be installed

You can then check that the jikes package, in this example, was not downgraded to the earlier version with the rpm –q command:

# rpm -q jikes

jikes-1.17-1

Transaction IDs

The rpm command gives every package installed a transaction ID. The transaction ID is a Unix time stamp (number of seconds since January 1, 1970). You can then perform some operations on packages based on the transaction ID.

Note

The fact that a transaction ID uses a Unix timestamp may change in the future.

All the packages installed at the same time are given the same transaction ID. This means that you can perform operations on a set of packages, the packages that were installed together.

But there’s also a downside to this. All the packages installed when you first installed or upgraded your Linux system are given the same transaction ID. This means you cannot selectively act on these packages using the transaction ID, because you will likely get far more packages than you want to work on.

Viewing RPM Transaction IDs

To view the install transaction ID (a date code) for a given package, you can use a command like the following:

$ rpm -q --qf "%-20{NAME} %-20{INSTALLTID}\n" jikes

jikes 1035589778

This command uses the --qf or --queryformat option to specify the data to return from the RPM query command. In this case, the command requests the name of the package as well as the transaction ID (TID) for installation.

Cross Reference

Chapter 5 describes the --queryformat option.

There is also a transaction ID for removal, the REMOVETID. You can also query for this ID. For example, if a package hasn't been removed, you'll see an entry like the following:

$ rpm -qa --qf "%-20{NAME} %-20{REMOVETID}\n" termcap

termcap (none)

Viewing the Packages Associated with a Transaction ID

Once you have a transaction ID, you can use the --tid option, short for transaction ID, to query for the package associated with a given transaction, using a command like the following:

$ rpm -q --tid 1035589778

jikes-1.17-1

This example uses the transaction ID that the earlier query example returned. If you installed more than one package at the same time, you will see a listing of all the packages that share the transaction ID.

For example, to see many packages with one transaction ID, you can query for packages installed when you installed or upgraded your version of Linux. First, query for the transaction ID of a package you know was installed with the Linux distribution, such as setup on a Red Hat system:

$ rpm -q --qf "%-20{NAME} %-20{INSTALLTID}\n" setup

setup 1033838323

Second, use this transaction ID and query for all packages with this ID, using code like the following:

$ rpm -q --tid 1033838323 | more

redhat-menus-0.26-1

glibc-2.2.93-5

cracklib-2.7-18

gdbm-1.8.0-18

gmp-4.1-4

libacl-2.0.11-2

libjpeg-6b-21

linc-0.5.2-2

pcre-3.9-5

shadow-utils-20000902-12

libtermcap-2.0.8-31

freetype-2.1.2-7

info-4.2-5

fileutils-4.1.9-11

psmisc-20.2-6

ntp-4.1.1a-9

mount-2.11r-10

cracklib-dicts-2.7-18

krb5-libs-1.2.5-6

cyrus-sasl-2.1.7-2

usermode-1.63-1

Xft-2.0-1

Note

Be sure to replace the transaction ID shown here with the transaction ID obtained by querying your system.

This example shows just a few of the packages installed when the Red Hat Linux was installed.

With these options, you can find the transaction IDs for given packages and can use the rpm command to install, remove, or otherwise modify the packages that share a transaction ID.

Rolling Back Transactions

The --rollback option to the rpm command allows you to roll back upgrades based on a time. Use a command like the following:

# rpm –U --rollback "3 months ago"

The --rollback option is very limited in what it can do. The --rollback option works only for packages that have been upgraded. You cannot rollback the initial installation of a package. This is to prevent you from accidentally rolling back all packages.

The --rollback option works best if you want to restore the system to a previous state, prior to performing any other RPM operations. That is, soon after you upgraded a package and decide that it isn’t working right. If you have modified the RPM system after performing the transaction you want to rollback, there may be unintended consequences if any new package depends on the packages you want to roll back. In addition, the --rollback option only works in limited situations but does not always report when these conditions are not met. The rpm command may simply do nothing, or it may remove packages you do not expect.

Warning

Before running the --rollback option, backup your RPM database as described in Chapter 5.

Because of all these limitations, rollbacks do not work in all situations. In place of the --rollback option, you can use the query shortcuts introduced in Chapter 5 and find the packages you have installed recently (if that is what you want to roll back). In this case, you can use the rpm command to remove the packages you want to get rid of and reinstall the packages you want to restore.

In many cases, this manual approach is safest, and you will have a clearer understanding about what was installed or upgraded on your system.

Saving Old Packages

When installing, removing, or upgrading, you can use the --repackage command-line option to save a version of something like the old package to a file, making a backup of the older package contents.

Warning

The package created by the --repackage option is not a complete RPM package. You can use the rpmbuild command to make it into a complete package, but by itself, it will not be a complete package. See Chapters 10, 11, and 12 for more on building packages.

You can later reinstall the old files, once they have been made into a complete package. This can be quite useful if something goes wrong or the upgraded package has bugs. You can fall back to the old package if needed.

By default, the --repackage option puts the old package in the /var/spool/repackage directory. Other common directories are /var/spool/up2date or /var/tmp. Your RPM configuration determines the directory used by this option.

Note

The up2date name comes from the Red Hat service for keeping a system up to date with regard to package versions.

For example, say you have a package, jikes (a Java programming language compiler used in previous examples) that you want to upgrade. But you are worried that the new version may not work properly.

First, check the version you have. For example:

# rpm -q jikes

jikes-1.14-1

This shows you are at version 1.14 of the jikes Java compiler. You can then upgrade to version 1.17 while repackaging the old version, as shown following:

# rpm -Uhv --repackage jikes-1.17-glibc2.2-1.i386.rpm

Preparing... ########################################### [100%]

Repackaging...

1:jikes ########################################### [100%]

Upgrading...

1:jikes ########################################### [100%]

This upgrade has kept a copy of the old package in the /var/spool/repackage directory. You can verify this with the following command:

$ ls -l /var/spool/repackage/

total 692

-rw-r--r-- 1 root root 703037 Oct 25 18:49 jikes-1.14-1.i386.rpm

You can see a version of the old package, with the old version number.

Warning

This is not the same as the original package. This is not a complete package.

The repackaged RPM contains a snapshot of the package’s files as they were on your hard disk, not as they were when you originally installed the package. Thus, the contents may differ if the files have changed on your hard disk. In addition, the --repackage option may not properly sign the package as the original was.

In addition to the --repackage option with the rpm command, you can use a free tool called rpmrebuild to make snapshots of any installed packages.

Written by Eric Gerbier, rpmrebuild allows you to create an RPM from the installed, and perhaps modified, version of a package. You don’t have to upgrade, remove, or install a new package, as you do with the --repackage option.

Download rpmrebuild from http://rpmrebuild.sourceforge.net/.

Summary

Transactions allow you to install multiple packages as a group and know that either all the packages will succeed in installing or none of them will. This is very important if you have a set of interlocking packages that you need to install.

All the packages you install, remove, or upgrade on the same command line are automatically made part of a transaction. The rpm command will ensure that all packages can be installed, removed, or upgraded, and will not perform the operation unless all will succeed.

All packages installed or removed are given a transaction ID, which uses a Unix timestamp (the number of seconds since January 1, 1970). All packages installed or removed at the same time are given the same transaction ID. You can then query by transaction IDs to perform operations on all the packages installed together.

The --repackage option tells the rpm command to make a backup RPM of the current package when you are installing or upgrading a more recent version or removing the package. By default, the backup RPM is placed in the /var/spool/repackage directory. Note that a package created this way is not exactly the same as the original package. Files may have changed on disk. In addition, packages created with the --repackage option are not real valid RPM packages. You cannot install these packages without performing extra operations to create a real RPM package from the repackaged data.

Chapter 07

Chris Ricker

2003-01-15T16:08:00

Eric Foster-Johnson