Памятка на
тему конфликтов чтения-записи и прочей
ACID-ности в БД Zope, ZODB.
ZODB provides
execution time consistency by raising read conflict errors. A simple
explanation of read conflict errors requires some extra details about
how ZODB works. ZODB transactions execute in parallel. When one
connection commits a transaction, it sends an invalidation message to
all the other connections; the invalidation messages lists all the
objects that were modified by the committed transaction. The next
time another connection commits a transaction, it will apply the
invalidation; i.e. it will ghostify all the objects in the
invalidation message.
If a connection is
asked to load an object from the database and it has received (but
not applied) an invalidation message for the object, it raises a
ReadConflictError. This error is necessary to avoid an inconsistent
read. When ZODB loads an object from storage, it always reads the
most recent revision. Since the connection has an invalidation
message for the object, the object was modified after the transaction
began. If it reads the current revision of that object, it could be
inconsistent with other objects read before the transaction began.
The way ZODB and
threading works is that each thread that uses the database gets its
own connection to the database. Each connection gets its own copy of
your object. All of the threads can read and change any of the
objects. ZODB keeps all of these objects synchronized between the
threads. The upshot is that you don’t have to do any locking or
thread synchronization yourself. Your code can act as though it is
single threaded.
However,
synchronization problems can occur when objects are changed by two
different threads at the same time.
Imagine that thread
1 gets its own copy of object A, as does thread 2. If thread 1
changes its copy of A, then thread 2 will not see those changes until
thread 1 commits them. In cases where lots of objects are changing,
this can cause thread 1 and 2 to try and commit changes to object 1
at the same time.
When this happens,
ZODB lets one transaction do the commit (it “wins”) and raises a
‘ConflictError’ in the other thread (which “looses”).
def writing_to_zdb(): zdb = open_db() retry = 0 while retry < max_retry: try: # this is where you write to, delete from, & change the DB # for example, this creates a new {} that is persistent zdb['root']['new_dict'] = PersistentDict() transaction.get().commit() except ConflictError: retry += 1 time.sleep(sleep_delay) pass else: break else: # retried too many times close_db(zdb) return "Error - transaction could not complete" close_db(zdb) return "Data written successfully" |
Еще?
original post http://vasnake.blogspot.com/2015/03/zope-zodb-acid.html
Комментариев нет:
Отправить комментарий