From bb9b9001adefe8f22435fe5f377eeb7663199634 Mon Sep 17 00:00:00 2001 From: Julia Kreger Date: Thu, 27 Jul 2023 10:01:31 -0700 Subject: [PATCH] DB: Select upon delete for allocations When an allocation has been created, it is still being created in the background. The client may request deletion of the allocation *prior* to the creation of the allocation is entirely completed. That is fine, but the challenge is we may encounter a locked row if we're asked to delete while in process. So, we'll query with with_for_update[0] which should be held until the lock is released, which is only released when the original locking transaction closes out[1][2]. [0]: https://docs.sqlalchemy.org/en/14/core/selectable.html#sqlalchemy.sql.expression.GenerativeSelect.with_for_update [1]: https://dev.mysql.com/doc/refman/5.7/en/select.html [2]: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html Change-Id: I0b68f054c951655b01f0cd776feb5a8c768471ab Closes-Bug: #2028866 --- ironic/db/sqlalchemy/api.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py index b5fa8528a5..fea11b772c 100644 --- a/ironic/db/sqlalchemy/api.py +++ b/ironic/db/sqlalchemy/api.py @@ -2392,7 +2392,11 @@ class Connection(api.Connection): query = add_identity_filter(query, allocation_id) try: - ref = query.one() + # NOTE(TheJulia): We explicitly need to indicate we intend + # to update the record so we block until the other users of + # the row are free, such as the process to match the + # allocation to a node. + ref = query.with_for_update().one() except NoResultFound: raise exception.AllocationNotFound(allocation=allocation_id)