Check for mysql SAVEPOINT error in retry decorator

Due to lost savepoints in mysql on deadlock errors, we can get
a non-existent savepoint error that is just masking a deadlock
error. This patch adjusts the retry decorator to check for these
savepoint errors as well. See the bug for more details about
the failure.

Closes-Bug: #1590298
Change-Id: I29905817ad7c69986f182ff3f0d58496608cd665
This commit is contained in:
Kevin Benton 2016-06-07 14:28:59 -07:00
parent 948461c8b2
commit f21eed3998
2 changed files with 9 additions and 1 deletions

View File

@ -37,7 +37,10 @@ MAX_RETRIES = 10
def is_retriable(e):
return _is_nested_instance(e, (db_exc.DBDeadlock, exc.StaleDataError))
if _is_nested_instance(e, (db_exc.DBDeadlock, exc.StaleDataError)):
return True
# looking savepoints mangled by deadlocks. see bug/1590298 for details.
return _is_nested_instance(e, db_exc.DBError) and '1305' in str(e)
is_deadlock = moves.moved_function(is_retriable, 'is_deadlock', __name__,
message='use "is_retriable" instead',

View File

@ -82,3 +82,8 @@ class TestDeadLockDecorator(base.BaseTestCase):
e = exceptions.MultipleExceptions([ValueError(), db_exc.DBDeadlock()])
with testtools.ExpectedException(exceptions.MultipleExceptions):
self._decorated_function(db_api.MAX_RETRIES + 1, e)
def test_mysql_savepoint_error(self):
e = db_exc.DBError("(pymysql.err.InternalError) (1305, u'SAVEPOINT "
"sa_savepoint_1 does not exist')")
self.assertIsNone(self._decorated_function(1, e))