From 6f35a8429939ec0f80deb2a65050c4b56db79545 Mon Sep 17 00:00:00 2001 From: Kevin_Zheng Date: Mon, 17 Aug 2015 10:32:23 +0800 Subject: [PATCH] Make query to quota usage table order preserved Currently, the query to quota usage table is not order preserved. This might cause deadlock in large-scale deployment: different calls may lock rows in different order, and deadlock will happen. This patch adds order_by to the query and make the query to the table order preserved. Change-Id: I98f6d7c3141349326c43cb32adcc1e6485ad53a6 Closes-bug: #1485408 --- nova/db/sqlalchemy/api.py | 7 ++++--- nova/tests/unit/db/test_db_api.py | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 85dd127a776f..6709d3571866 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3367,9 +3367,10 @@ def _get_project_user_quota_usages(context, session, project_id, rows = model_query(context, models.QuotaUsage, read_deleted="no", session=session).\ - filter_by(project_id=project_id).\ - with_lockmode('update').\ - all() + filter_by(project_id=project_id).\ + order_by(models.QuotaUsage.id.asc()).\ + with_lockmode('update').\ + all() proj_result = dict() user_result = dict() # Get the total count of in_use,reserved diff --git a/nova/tests/unit/db/test_db_api.py b/nova/tests/unit/db/test_db_api.py index 7e91ed4d9868..31ef62c33fc8 100644 --- a/nova/tests/unit/db/test_db_api.py +++ b/nova/tests/unit/db/test_db_api.py @@ -6718,6 +6718,13 @@ class QuotaTestCase(test.TestCase, ModelsObjectComparatorMixin): self.assertEqual(expected, db.quota_usage_get_all_by_project_and_user( self.ctxt, 'p1', 'u1')) + def test_get_project_user_quota_usages_in_order(self): + _quota_reserve(self.ctxt, 'p1', 'u1') + with mock.patch.object(query.Query, 'order_by') as order_mock: + sqlalchemy_api._get_project_user_quota_usages( + self.ctxt, None, 'p1', 'u1') + self.assertTrue(order_mock.called) + def test_quota_usage_update_nonexistent(self): self.assertRaises(exception.QuotaUsageNotFound, db.quota_usage_update, self.ctxt, 'p1', 'u1', 'resource', in_use=42)