<div dir="ltr"><span id="docs-internal-guid-be63c6ad-87fe-d9f6-cacf-4a7a3e46c66b"><p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:transparent">Hello everyone!</span></p>
<br><p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:transparent">Some recent change requests ([1], [2]) show that there is a number of issues with locking db resources in Neutron.</span></p>
<br><p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap;background-color:transparent">One of them is initialization of drivers which can be performed simultaneously by several neutron servers. In this case locking is essential for avoiding conflicts which is now mostly done via using </span><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">SQLAlchemy's with_lockmode() method, which emits SELECT..FOR UPDATE resulting in rows being locked within a transaction. As it has been already stated by Mike Bayer [3], this statement is not supported by Galera and, what’s more, by Postgresql for which a lock doesn’t work in case when a table is empty.</span></p>
<br><p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">That is why there is a need for an easy solution that would allow cross-server locking and would work for every backend. First thing that comes into mind is to create a table which would contain all locks acquired by various pieces of code. Each time a code, that wishes to access a table that needs locking, would have to perform the following steps:</span></p>
<p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">1. Check whether a lock is already acquired by using SELECT lock_name FROM cross_server_locks table.</span></p>
<p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">2. If SELECT returned None, acquire a lock by inserting it into the cross_server_locks table.</span></p>
<p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">    In other case wait and then try again until a timeout is reached.</span></p>
<p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">3. After a code has executed it should release the lock by deleting the corresponding entry from the cross_server_locks table.</span></p>
<p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap"> </span></p><p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt">
<span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">The locking process can be implemented by decorating a function that performs a transaction by a special function, or as a context manager.</span></p>
<br><p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">Thus, I wanted to ask the community whether this approach deserves consideration and, if yes, it would be necessary to decide on the format of an entry in cross_server_locks table: how a lock_name should be formed, whether to support different locking modes, etc.</span></p>
<br><br><p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">[1] </span><a href="https://review.openstack.org/#/c/101982/" style="text-decoration:none"><span style="font-size:15px;font-family:Arial;text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">https://review.openstack.org/#/c/101982/</span></a></p>
<p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">[2] <a href="https://review.openstack.org/#/c/107350/">https://review.openstack.org/#/c/107350/</a></span></p>
<p dir="ltr" style="line-height:1.15;margin-top:0pt;margin-bottom:0pt"><span style="font-size:15px;font-family:Arial;color:rgb(0,0,0);vertical-align:baseline;white-space:pre-wrap">[3] <a href="https://wiki.openstack.org/wiki/OpenStack_and_SQLAlchemy#Pessimistic_Locking_-_SELECT_FOR_UPDATE">https://wiki.openstack.org/wiki/OpenStack_and_SQLAlchemy#Pessimistic_Locking_-_SELECT_FOR_UPDATE</a></span></p>
<br></span></div>