Use db_api.retry_db_errors in quota engine

The quota engine was still using oslo_db wrap_db_retry
which does not automatically take into account deadlocks
that occur inside of nested savepoint transactions.

In one case it didn't matter because it passed in the correct
exception checker but in the one that protected 'set_quota_usage'
it did not use is_retriable so a deadlock inside of the savepoint
would have resulted in a much more expensive retry all of the way
up at the API layer.

This patch just adjusts them to both use the standard neutron
retry_db_errors decorator.

Change-Id: I1e45eb15f14bf35881e5b1dce77733e831e9c6b1
Related-Bug: #1596075
This commit is contained in:
Kevin Benton 2016-07-18 22:39:19 -06:00
parent 45ce07fa08
commit c46edbc7d6
3 changed files with 3 additions and 14 deletions

View File

@ -217,7 +217,7 @@ In order to ensure correct operations, a row-level lock is acquired in
the transaction which creates the reservation. The lock is acquired when
reading usage data. In case of write-set certification failures,
which can occur in active/active clusters such as MySQL galera, the decorator
oslo_db.api.wrap_db_retry will retry the transaction if a DBDeadLock
neutron.db.api.retry_db_errors will retry the transaction if a DBDeadLock
exception is raised.
While non-locking approaches are possible, it has been found out that, since
a non-locking algorithms increases the chances of collision, the cost of

View File

@ -14,7 +14,6 @@
# under the License.
from neutron_lib import exceptions
from oslo_db import api as oslo_db_api
from oslo_log import log
from neutron.common import exceptions as n_exc
@ -157,11 +156,7 @@ class DbQuotaDriver(object):
quota_api.remove_expired_reservations(
context, tenant_id=tenant_id)
@oslo_db_api.wrap_db_retry(max_retries=db_api.MAX_RETRIES,
retry_interval=0.1,
inc_retry_interval=True,
retry_on_request=True,
exception_checker=db_api.is_retriable)
@db_api.retry_db_errors
def make_reservation(self, context, tenant_id, resources, deltas, plugin):
# Lock current reservation table
# NOTE(salv-orlando): This routine uses DB write locks.

View File

@ -13,8 +13,6 @@
# under the License.
from oslo_config import cfg
from oslo_db import api as oslo_db_api
from oslo_db import exception as oslo_db_exception
from oslo_log import log
from oslo_utils import excutils
from sqlalchemy import event
@ -209,11 +207,7 @@ class TrackedResource(BaseResource):
# can happen is two or more workers are trying to create a resource of a
# give kind for the same tenant concurrently. Retrying the operation will
# ensure that an UPDATE statement is emitted rather than an INSERT one
@oslo_db_api.wrap_db_retry(
max_retries=db_api.MAX_RETRIES,
exception_checker=lambda exc:
isinstance(exc, (oslo_db_exception.DBDuplicateEntry,
oslo_db_exception.DBDeadlock)))
@db_api.retry_db_errors
def _set_quota_usage(self, context, tenant_id, in_use):
return quota_api.set_quota_usage(
context, self.name, tenant_id, in_use=in_use)