#header-inner {background-position: right !important; width: 100% !important;}

8/26/15

Transactions.

1. Introduction.

Certain services require that operations with these adhere to a few of principles.

Atomicity,
Consistency,
Isolation,
Durability,

details in an article named ACID.

to fulfill requirements of 'atomicity' & 'durability' despite failure, data objects have to be 'recoverable'.

when server stops due to hardware or software failure, all of transaction-related data has to be available in a persistent memory, so the data can be 'recovered', preserving effects of 'all or nothing'.

to provide 'isolation', data should be processed in either serial way (one operation after another, without concurrency) or when this is not an option (most services require concurrent processing of multiple operations at once), in a serially-equivalent way.

'consistency' is an issue of transactional service's user, mostly.

transactional services in practice are operations that are contained within a construct called 'transaction', that is, between brackets of 'Open Transaction' operation & 'Close Transaction' operation. 'Close Transaction' can be either 'Commit' (keep changes, all of them) or 'Rollback' (abort changes, all of them).

each of transaction has identifier TID, that allows operation to be associated with transaction with that an identifier.

transactional services might allow for a certain amount of time before 'commit', after that time operation is 'aborted', 'rolled back'.


2. Issues of Concurrency.


2.1. Lost updates.

'Lost updates' is an issue, that can be shown using example with bank-alike operations on accounts A, B & C.

Transaction TTransaction U
accountBalance = A.read();$100
A.write(accountBalance - 4); $96
accountBalance = C.read();$300
C.write(accountBalance - 3);$297
accountBalance = B.read();$200
accountBalance = B.read()$200
B.write(accountBalance + 3)$203
B.write(accountBalance + 4)$204


'Transaction T' & 'Transaction U' use different threads, each of these use private variables & state.

there's issue with coordinating the concurrency of 'conversations' between a 'bank server' & 'clients'.


2.2. Inconsistent reads.

'Inconsistent reads' is also an issue, that can be shown using example with bank-alike operations on accounts A, B & C.

Transaction TTransaction U
accountBalance = A.read();$200
A.write(accountBalance - 100); $100
accountBalance = A.read();$100
accountBalance = accountBalance + B.read();$300
accountBalance = accountBalance + C.read();$300
accountBalance = B.read();$200
B.write(accountBalance + 100)$300


again,

'Transaction T' & 'Transaction U' use different threads, each of these use private variables & state.

there's issue with coordinating the concurrency of 'conversations' between a 'bank server' & 'clients'.


2.3. Serial equivalence.

if all known transactions executed serially give correct result(s), then if there are orderings in which they also give correct result(s), then these orderings are 'serially equivalent'.


2.4. Possible approaches to handling concurrency.


2.4.1. Locking.

Every data object is locked (taken) by a transaction reaching for it.

No other transaction can use that object until first transaction either 'commits' or 'rolls back'.


2.4.2. Optimistic concurrency management.

it's about 'hope' ... in that there won't be any 'conflicts' with data access.

if there's conflict, transaction needs to be aborted & repeated again, probably.


2.4.3. Timestamps.

with this approach, each of transactions has a timestamp.

data objects get these timestamps with each contact.

transaction rollback & recovery happens when they are too late to perform operation on a given object.


3. Recoverability.

transactional services must persist results of all 'committed' transactions & remove traces of 'rolled back' transactions.

there are two issues of 'dirty reads' & 'premature writes', both possible even with 'serially equivalent transaction execution'.


3.1. Dirty reads.

'isolation' property of a transaction requires that transactions won't read 'uncommitted states' of other transactions.

a case of a 'dirty read' is when this undesired occurance happens nevertheless.


'reproductibility' of a transaction occurs when we delay 'committing' a transaction that did a 'dirty read' from other transaction(s).


'cascade aborts' occur when one 'rollback' causes a serie of 'rollbacks' in 'waiting transactions', due to a 'dirty read' & 'delaying commits' as in a case mentioned above.


3.2. Premature writes.

'premature write' occurs when we write in a data object changed by another transaction, before its 'commit' or 'rollback'.

to prevent data inconsistency, to ensure correct results, write operations must be delayed until previous transactions that updated 'same' data objects either 'commit' or 'rollback'.


3.3. Strict transaction execution.

generally speaking, we can say that its neccessary to delay transactions' read & write operations to avoid 'dirty read' & 'premature write' issues.

transaction execution is called 'strict' when services delay both 'read' & 'write' operations on 'data objects' until all of transactions that wrote in that 'data object' are either 'committed' or 'rolled back'.

'strict' transaction execution enforces needed property of 'isolation'.


3.4. Temporary versions.

transactional services should be designed the way that it is possible to delete any of the updates in data objects, when changes are aborted.

to enable this, many of implementations use temporary values' collections, with each of data objects & it's updates stored in a volatile (non-permanent) memory.

when transactions commit changes, state changes are moved into 'data objects', 'persisted' in one step, during which other transactions cannot interact with these 'data objects'.


4. Nested transactions.

transaction can consist of a set of 'nested transactions'.

each of these 'nested transactions' can consist of a similar set of 'nested transactions' & so on ...

for example, there can be 'moneyTransfer' transaction that consists of 'withdraw' & 'deposit' nested transactions.



'nested transactions' are useful because of:

- transactions nested on the same level can be performed concurrently (at the same time) with other nested transaction(s),
- nested transaction may be 'committed' or 'rolled back' independently. a 'rollback' of one or few of 'nested transactions' might not be a cause of parent transaction's 'rollback' yet,
- nested transactions are especially useful in 'distributed systems', because children nested transactions can be performed concurrently on different servers. this should be elaborated in another article.

Source: [13].

See also if You wish or need ... : Parallel & Distributed Systems, Stitie Space.

No comments:

Post a Comment