Remove SELECT FOR UPDATE use in ML2 type driver release_segment

SELECT FOR UPDATE expression, which is triggered with the use of the
SQLAlchemy Query object's with_lockmode('update') method, is
detrimental to performance and scalability of the database
performance code in Neutron due to the lock contention it produces.

SELECT FOR UPDATE can be entirely avoided in release_segment methods
with the use of single-shot UPDATE and DELETE expressions, and this
patch clears a number of uses of SELECT FOR UPDATE by consolidating
multiple SQL expressions into one.

Partial-Bug: #1330562
Change-Id: I29ffcafc8d4d73ac1cb50c94df5da85514d47a3f
This commit is contained in:
Cedric Brandily
2014-06-16 22:56:10 +02:00
parent 0929cccffb
commit 1814dae6b7
4 changed files with 64 additions and 69 deletions

View File

@@ -108,24 +108,22 @@ class GreTypeDriver(type_tunnel.TunnelTypeDriver):
def release_segment(self, session, segment):
gre_id = segment[api.SEGMENTATION_ID]
inside = any(lo <= gre_id <= hi for lo, hi in self.gre_id_ranges)
with session.begin(subtransactions=True):
try:
alloc = (session.query(GreAllocation).
filter_by(gre_id=gre_id).
with_lockmode('update').
one())
alloc.allocated = False
for lo, hi in self.gre_id_ranges:
if lo <= gre_id <= hi:
LOG.debug(_("Releasing gre tunnel %s to pool"),
gre_id)
break
else:
session.delete(alloc)
LOG.debug(_("Releasing gre tunnel %s outside pool"),
gre_id)
except sa_exc.NoResultFound:
LOG.warning(_("gre_id %s not found"), gre_id)
query = session.query(GreAllocation).filter_by(gre_id=gre_id)
if inside:
count = query.update({"allocated": False})
if count:
LOG.debug("Releasing gre tunnel %s to pool", gre_id)
else:
count = query.delete()
if count:
LOG.debug("Releasing gre tunnel %s outside pool", gre_id)
if not count:
LOG.warning(_("gre_id %s not found"), gre_id)
def _sync_gre_allocations(self):
"""Synchronize gre_allocations table with configured tunnel ranges."""