57
Sometimes an update to a memory-resident data structure will require multiple
instructions, so naturally those changes can be torn by power failure as well since power
could be lost between any two instructions. Runtime locking prevents other threads from
seeing a partially done change, but locking doesn’t provide any failure atomicity. When
an application needs to make a change that is larger than 8 bytes to persistent memory, it
must construct the atomic operation by building on top of the basic atomics provided by
hardware, such as the 8-byte failure atomicity provided by Intel hardware.
Transactions
Combining multiple operations into a single atomic operation is usually referred to as
a transaction. In the database world, the acronym ACID describes the properties of a
transaction: atomicity, consistency, isolation, and durability.
Atomicity
As described earlier, atomicity is when multiple operations are composed into a single
atomic action that either happens entirely or does not happen at all, even in the face of
system failure. For persistent memory, the most common techniques used are
• Redo logging, where the full change is first written to a log, so during
recovery, it can be rolled forward if interrupted.
• Undo logging, where information is logged that allows a partially
done change to be rolled back during recovery.
• Atomic pointer updates, where a change is made active by updating
a single pointer atomically, usually changing it from pointing to old
data to new data.
The preceding list is not exhaustive, and it ignores the details that can get relatively
complex. One common consideration is that transactions often include memory
allocation/deallocation. For example, a transaction that adds a node to a tree data
structure usually includes the allocation of the new node. If the transaction is rolled back,
the memory must be freed to prevent a memory leak. Now imagine a transaction that
performs multiple persistent memory allocations and free operations, all of which must
be part of the same atomic operation. The implementation of this transaction is clearly
more complex than just writing the new value to a log or updating a single pointer.
Chapter 4 Fundamental ConCepts oF persistent memory programming
Sometimes an update to a memory-resident data structure will require multiple
instructions, so naturally those changes can be torn by power failure as well since power
could be lost between any two instructions. Runtime locking prevents other threads from
seeing a partially done change, but locking doesn’t provide any failure atomicity. When
an application needs to make a change that is larger than 8 bytes to persistent memory, it
must construct the atomic operation by building on top of the basic atomics provided by
hardware, such as the 8-byte failure atomicity provided by Intel hardware.
Transactions
Combining multiple operations into a single atomic operation is usually referred to as
a transaction. In the database world, the acronym ACID describes the properties of a
transaction: atomicity, consistency, isolation, and durability.
Atomicity
As described earlier, atomicity is when multiple operations are composed into a single
atomic action that either happens entirely or does not happen at all, even in the face of
system failure. For persistent memory, the most common techniques used are
• Redo logging, where the full change is first written to a log, so during
recovery, it can be rolled forward if interrupted.
• Undo logging, where information is logged that allows a partially
done change to be rolled back during recovery.
• Atomic pointer updates, where a change is made active by updating
a single pointer atomically, usually changing it from pointing to old
data to new data.
The preceding list is not exhaustive, and it ignores the details that can get relatively
complex. One common consideration is that transactions often include memory
allocation/deallocation. For example, a transaction that adds a node to a tree data
structure usually includes the allocation of the new node. If the transaction is rolled back,
the memory must be freed to prevent a memory leak. Now imagine a transaction that
performs multiple persistent memory allocations and free operations, all of which must
be part of the same atomic operation. The implementation of this transaction is clearly
more complex than just writing the new value to a log or updating a single pointer.
Chapter 4 Fundamental ConCepts oF persistent memory programming
