cinder dbapiのsqlalchemyトランザクションロック管理
2162 ワード
頻繁に同時操作が必要なテーブルに対して、sqlalchemyはロックをかけてデータの一貫性を保証することができます.
with_lockmode(mode)オプションmodeパラメータの説明:
modeパラメータ
説明
None
translates to no lockmode
'update'
translates to
'update_nowait'
translates to
'read'
translates to
cinder dbapiでデッドロックを処理する方法,
with_lockmode('update')
:with_lockmode(mode)オプションmodeパラメータの説明:
modeパラメータ
説明
None
translates to no lockmode
'update'
translates to
FOR UPDATE
(standard SQL, supported by most dialects) 'update_nowait'
translates to
FOR UPDATE NOWAIT
(supported by Oracle, PostgreSQL 8.1 upwards) 'read'
translates to
LOCK IN SHARE MODE
(for MySQL), and FOR SHARE
(for PostgreSQL) def _get_quota_usages(context, session, project_id):
# Broken out for testability
rows = model_query(context, models.QuotaUsage,
read_deleted="no",
session=session). \
filter_by(project_id=project_id). \
order_by(models.QuotaUsage.id.asc()). \
with_lockmode('update'). \
all()
return {row.resource: row for row in rows}
cinder dbapiでデッドロックを処理する方法,
_retry_on_deadlock(f)
def _retry_on_deadlock(f):
"""Decorator to retry a DB API call if Deadlock was received."""
@functools.wraps(f)
def wrapped(*args, **kwargs):
while True:
try:
return f(*args, **kwargs)
except db_exc.DBDeadlock:
LOG.warning(_LW("Deadlock detected when running "
"'%(func_name)s': Retrying..."),
dict(func_name=f.__name__))
# Retry!
time.sleep(0.5)
continue
functools.update_wrapper(wrapped, f)
return wrapped
@require_context
@_retry_on_deadlock
def reservation_commit(context, reservations, project_id=None):
_retry_on_deadlock(f)
論理は簡単で、すなわちデッドロック異常dbを捕まえる.Exc.DBDeadlockは、0.5秒後に再実行されます.呼び出し方法はdb関数としてのコメントラベルです[email protected](f)とfunctools.update_wrapper(wrapped,f)は、注釈される方法を__保持するためであるname__ および_doc__ などのプロパティについては、「Python-ステップアップ-functoolsモジュールのまとめ」を参照してください.