Definition

The atomicity of actions on a database is a fundamental guarantee that database systems provide to application programs. Whatever state modifications an atomic action may perform are guaranteed to be executed in an all-or-nothing manner: either all state changes caused by the action will be installed in the database or none. This property is important in the potential presence of failures that could interrupt the atomic action. The database system prepares itself for this case by logging state modifications and providing automated recovery as part of the failure handling or system restart. These implementation aspects are transparent to the application program and are thus a major relief for the programs’ failure handling and boost the application development productivity.

Historical Background

Since the early 1970s (or even earlier), transaction processing systems for airline reservations and debit/credit banking had means for recovery and concurrency control that were similar to atomic actions. However, these implementation techniques were hardly documented in publicly available literature and still far from a principled, universal solution. The major credit for the modern concept of atomicity (and transactions) belongs to the 1998 Turing Award winner Jim Gray [1530,1531,8]. Closely related notions of atomic actions have been proposed by other authors at around the same time, including [1535,12,13], which in turn were inspired by the informal work on “spheres of control” by Bjork and Davies [3, 4].

Foundations

As an example for the importance of atomic actions, consider a sequence of steps that read and write two bank-account records, x and y, in order to transfer some amount of money from account x to account y:

$$ \begin{array}{l}\mathrm{T}1:\mathrm{R}\left(\mathrm{x}\right)\mathrm{W}\left(\mathrm{x}\right)\quad\quad\quad \mathrm{R}\left(\mathrm{y}\right)\mathrm{W}\left(\mathrm{y}\right)\\ {}\mathrm{T}2:\quad\quad\quad \mathrm{R}\left(\mathrm{x}\right)\mathrm{R}\left(\mathrm{y}\right)\end{array} $$

If there is a system failure after writing x but before writing y, the underlying database becomes inconsistent, with the transferred money seemingly lost in “mid-flight.” Even worse, the application program may not even know if this problem actually occurred or not (the system may have succeeded in writing y just before it crashed but could not send a return code anymore). If, on the other hand, the database system executes the entire step sequence as an atomic action, the failure handling for the application program becomes much simpler as it can always restart on a clean, consistent database.

In database systems the atomic actions themselves can be flexibly defined by the application programs, by demarcating the begin and end of a transaction with explicit interface calls. For example, an entire sequence of SQL command invocations can be made atomic. By default, usually every individual SQL operation is guaranteed to be atomic. These guarantees are part of the transactional ACID properites: atomicity, consistency-preservation, isolation, and durability [8]. In some scientific communities outside of database systems research, atomicity is meant to include the isolation guarantee. Atomic actions are then (alternatively) defined to be state-modification sequences whose effects are ensured (by the underlying run-time environment) to be equivalent to indivisible actions with all effect appearing to be instantaneous upon the completion of the entire sequence. In the presence of concurrent accesses to the same shared data, this combined atomicity/isolation property provides the illusion, despite the fact that in reality accesses by different programs are interleaved. Defining this principle in formal terms leads to the concept of serializability and methods for concurrency control as part of the database (or other run-time) system [2, 6, 14].

As an example for the importance of isolation (as an additional property of atomic actions), consider an extended variant of the earlier example. Assume to the money-transfer process – now viewed as a transaction T1 – a second transaction T2 reads both bank-account records x and y in order to analyze financial portfolios and perform some kind of risk assessment. The following concurrent execution, with time proceeding from left to right, could be possible:

$$ \mathrm{T}1:\mathrm{R}\left(\mathrm{x}\right)\mathrm{W}\left(\mathrm{x}\right)\quad\quad\quad \mathrm{R}\left(\mathrm{y}\right)\mathrm{W}\left(\mathrm{y}\right) $$
$$ \mathrm{T}2:\quad\quad\quad \mathrm{R}\left(\mathrm{x}\right)\mathrm{R}\left(\mathrm{y}\right) $$

With this step interleaving, transaction T2 would see an inconsistent database, namely, the state of x after money is withdrawn from x and the state of y before money is deposited there. This may lead to a distorted analysis and false conclusions in the decision-making of a financial broker. Running both T1 and T2 as atomic and isolated transactions would prevent this particular interleaving and guarantees that only such executions are allowed that are provably equivalent to a sequential execution where such an anomaly is impossible.

The atomicity guarantee includes all “side effects” of an action as far as the database state is concerned. For example, the effects of a database trigger are covered by the guarantee, but effects outside of the database such as sending a message are outside the scope of the database system guarantees. Modern application servers and message brokers, on the other hand, may provide such guarantees about messages (e.g., atomic multicasts) and application state (e.g., specific program variables) beyond the database. A traditional implementation technique to this end is to support failure-resilient queues. Modern database systems have integrated such message queues and application state management and extend their atomic actions to them, providing more comprehensive application recovery. A new research trend in programming languages is to provide atomicity guarantees to arbitrary programs, not just database applications, in order to simplify exception handling and generally ease programmers’ work. For example, method invocations in an object-oriented language could be made atomic by means of an underlying transactional memory as part of the language’s run-time system (and possibly even hardware architecture).

The atomicity concept simplifies failure handling at the application program level, but it does not mask failures. Rather a typical approach is that the program notices the failing of an atomic action by a corresponding system return code (for the atomic action invocation itself, for the end-of-action demarcation call, or upon the next interaction with the database system if the previous call simply timed out without any response) and then has to retry the action. This paradigm still requires explicit coding for the retrying, and this may require special care about nonidempotent effects or additional system guarantees and state testing for ensuring idempotence. Some advanced methods for application recovery can automate these retrials and testing for nonidempotence, thus strengthening the all-or-nothing guarantee for atomicity into an exactly once execution guarantee with complete failure masking [1].

On the other hand, for some data-intensive applications outside of database systems, atomicity may be an overly strong property if applied to entire processes; this holds particularly for long-lived workflows and cooperative work. Although these applications still benefit from atomic actions for smaller-grained operations, additional forms of relaxed atomicity or extended atomicity would be desirable. The database research community has developed a variety of such models, most notably the model of open nested transactions and the ACTA framework [5, 9].

Future Directions

Atomicity is a ground-breaking, fundamental contribution that first emerged in database systems but is increasingly pursued also by other research communities like programming languages, operating systems, dependable system design, and also formal reasoning and program verification [10]. There are several strategic reasons for this growing interest and extended application of atomic actions:

  • Web services, long-running workflows across organizations, large scale peer-to-peer platforms, and ambient-intelligence environments with huge numbers of mobile and embedded sensor/actor devices critically need support for handling or even masking concurrency and component failures and may mandate rethinking the traditional atomicity concept.

  • There is a proliferation of open systems where applications are constructed from preexisting components. The components and their configurations are not known in advance, and they can change on the fly. Thus, it is crucial that atomicity properties of components are composable and that one can predict and reason about the behavior of the composite system.

  • Modern applications and languages like Java lead millions of developers into concurrent programming. This is a drastic change from the classical situation where only a few hundred “five-star wizard” system programmers and a few thousand programmers working in scientific computing on parallel supercomputers would have to cope with the inherently complex issues of concurrency and advanced failure handling.

  • On an even broader scale, the drastically increasing complexity of the new and anticipated applications will require enormous efforts and care towards dependable systems or it may lead into a major “dependability crisis.” Atomicity is an elegant basic asset to build on in the design, implementation, and composition of complex systems and the reasoning about system behavior and guaranteed properties.

Cross-References