<div dir="ltr">><span style="font-size:12.8px">While opt.2 only prevents the conflicting changes, but does not guarantee that </span><span style="font-size:12.8px">the object does not change while within the context,</span><div><br></div><div>I'm not sure what you mean here. In a multi-writer galera cluster both SELECT FOR UPDATE and CAS won't fail until commit time if someone writes to another server.</div><div>So the DB lock only provides the conflicting change guarantee in a single-writer mysql setup.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, May 12, 2016 at 11:26 AM, Ilya Chukhnakov <span dir="ltr"><<a href="mailto:ichukhnakov@mirantis.com" target="_blank">ichukhnakov@mirantis.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi everyone.<br>
<br>
I’ve recently found that straightforward use of NeutronDbObject is prone to<br>
concurrency-related problems.<br>
<br>
I’ve submitted a patch set [3] with some tests to show that without special<br>
treatment using NeutronDbObject could lead to unexpected results.<br>
<br>
Further patch sets will provide acquire_object/acquire_objects contextmanager<br>
methods to the NeutronDbObject class. These methods are to be used in place of<br>
get_object/get_objects whenever the user intends to make changes to the object.<br>
These methods would start an autonested_transaction.<br>
<br>
There are (at least) two potential options for the implementation:<br>
<br>
1. Based on the DB locks (e.g. SELECT FOR UPDATE/SqlAlchemy with_for_update).<br>
<br>
   pros:<br>
     - the object is guaranteed to not be changed while within the context<br>
<br>
   cons:<br>
     - prone to deadlocks ([1] and potentially when locking multiple objects)<br>
<br>
2. Lock-free CAS based on object version counter. Can use SqlAlchemy version<br>
   counter [2] or add our own. If conflicting changes are detected upon exiting<br>
   the context (i.e. version counter held differs from the one in the DB), will<br>
   raise OSLO RetryRequest exception.<br>
<br>
   pros:<br>
     - does not require locking<br>
<br>
   cons:<br>
     - require an additional field in the models<br>
<br>
While opt.2 only prevents the conflicting changes, but does not guarantee that<br>
the object does not change while within the context, opt.1 may seem<br>
preferential. But even with opt.1 the user should not expect that the changes<br>
made to the object while within the context will get to the database as the<br>
autonested_transaction could fail on flush/commit.<br>
<br>
So I’d like to hear others’ opinion on the problem and which of the two<br>
implementation options would be preferred? Or maybe someone has a better idea.<br>
<br>
[1] <a href="https://wiki.openstack.org/wiki/OpenStack_and_SQLAlchemy#MySQLdb_.2B_eventlet_.3D_sad" rel="noreferrer" target="_blank">https://wiki.openstack.org/wiki/OpenStack_and_SQLAlchemy#MySQLdb_.2B_eventlet_.3D_sad</a><br>
[2] <a href="http://docs.sqlalchemy.org/en/rel_0_9/orm/versioning.html" rel="noreferrer" target="_blank">http://docs.sqlalchemy.org/en/rel_0_9/orm/versioning.html</a><br>
<br>
[3] <a href="https://review.openstack.org/#/c/315705/" rel="noreferrer" target="_blank">https://review.openstack.org/#/c/315705/</a><br>
<br>
--<br>
Thanks,<br>
Ilya<br>
__________________________________________________________________________<br>
OpenStack Development Mailing List (not for usage questions)<br>
Unsubscribe: <a href="http://OpenStack-dev-request@lists.openstack.org?subject:unsubscribe" rel="noreferrer" target="_blank">OpenStack-dev-request@lists.openstack.org?subject:unsubscribe</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" rel="noreferrer" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
</blockquote></div><br></div>