Commit ebb95ed2 authored by Tim Peters's avatar Tim Peters

Checkpointing review progress.

parent b1cbf426
...@@ -17,16 +17,17 @@ Multi-version concurrency control tests ...@@ -17,16 +17,17 @@ Multi-version concurrency control tests
Multi-version concurrency control (MVCC) exploits storages that store Multi-version concurrency control (MVCC) exploits storages that store
multiple revisions of an object to avoid read conflicts. Normally multiple revisions of an object to avoid read conflicts. Normally
when an object is read from the storage, its most recent revisions is when an object is read from the storage, its most recent revision is
read. Under MVCC, an older revision is read so that the transaction read. Under MVCC, an older revision may be read so that the transaction
sees a consistent view of the database. sees a consistent view of the database.
ZODB guarantees execution-time consistency: A single transaction will ZODB guarantees execution-time consistency: A single transaction will
always see a consistent view of the database while it is executing. always see a consistent view of the database while it is executing.
If transaction A is running, has already read an object O1, and an If transaction A is running, has already read an object O1, and a
external transaction B modifies object O2, then transaction A can no different transaction B modifies object O2, then transaction A can no
longer read the current revision of O2. It must either read the longer read the current revision of O2. It must either read the
version of O2 that is consistent with O1 or raise a ReadConflictError. version of O2 that is consistent with O1 or raise a ReadConflictError.
When MVCC is in use, A will do the former.
This note includes doctests that explain how MVCC is implemented (and This note includes doctests that explain how MVCC is implemented (and
test that the implementation is correct). The tests use a test that the implementation is correct). The tests use a
...@@ -61,26 +62,31 @@ Connection high-water mark ...@@ -61,26 +62,31 @@ Connection high-water mark
-------------------------- --------------------------
The ZODB Connection tracks a transaction high-water mark, which The ZODB Connection tracks a transaction high-water mark, which
represents the latest transaction id that can be read by the current bounds the latest transaction id that can be read by the current
transaction and still present a consistent view of the database. When transaction and still present a consistent view of the database.
a transaction commits, the database sends invalidations to all the Transactions with ids up to but not including the high-water mark
other transactions; the invalidation contains the transaction id and are OK to read. When a transaction commits, the database sends
the oids of modified objects. The Connection stores the high-water invalidations to all the other connections; the invalidation contains
mark in _txn_time, which is set to None until an invalidation arrives. the transaction id and the oids of modified objects. The Connection
stores the high-water mark in _txn_time, which is set to None until
an invalidation arrives.
>>> cn = db.open() >>> cn = db.open()
>>> print cn._txn_time
None
>>> cn.invalidate(100, dict.fromkeys([1, 2]))
>>> cn._txn_time >>> cn._txn_time
>>> cn.invalidate(1, dict.fromkeys([1, 2])) 100
>>> cn.invalidate(200, dict.fromkeys([1, 2]))
>>> cn._txn_time >>> cn._txn_time
1 100
>>> cn.invalidate(2, dict.fromkeys([1, 2]))
>>> cn._txn_time
1
The high-water mark is set to the transaction id of the first A connection's high-water mark is set to the transaction id taken from
transaction, because transaction ids must be monotonically increasing. the first invalidation processed by the connection. Transaction ids are
It is reset at transaction boundaries. monotonically increasing, so the first one seen during the current
transaction remains the high-water mark for the duration of the
transaction.
XXX We'd like simple abort and commit calls to make txn boundaries, XXX We'd like simple abort and commit calls to make txn boundaries,
but that doesn't work unless an object is modified. sync() will abort but that doesn't work unless an object is modified. sync() will abort
...@@ -107,7 +113,7 @@ The second connection has its high-water mark set now. ...@@ -107,7 +113,7 @@ The second connection has its high-water mark set now.
True True
It is safe to read "b," because it was not modified by the concurrent It is safe to read "b," because it was not modified by the concurrent
transaction. transaction.
>>> r2 = cn2.root() >>> r2 = cn2.root()
>>> r2["b"]._p_serial < cn2._txn_time >>> r2["b"]._p_serial < cn2._txn_time
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment