͋ΒΏΔࣄΛඞવԽ͠ɺ ੈͷதͷϛεϚονΛͳ͘͢ ݸਓ͕࣋ͭ͞·͟·ͳ࠽ೳͱɺੈքͱͷແݶʹ͋Γ·͢ɻ ఱ৬ͱͷग़͍͋ͷΑ͏ʹɺʮϛεϚονͷʯΛഉআ͠ɺʮ࠷దͳʯͱଓͰ͖Εɺ ਓʑྗΛ࠷େݶʹൃش͠ɺΑΓ͍͖͍͖ͱͨ͠ঢ়ଶΛ࣮ݱͰ͖ΔͣͰ͢ɻ ͋ͳͨͷݸੑΛٻΊΔਓ͕ݱΕΔͷɺ-"13"4ͳΒܾͯ͠ۮવͰ͋Γ·ͤΜɻ -"13"4"*ٕज़Λͱʹɺ͋ΒΏΔਓΛجʹใΛ࠶ߏங͠ɺ ৽͍͠αʔϏεΛ͠·͢ɻ M I S S I O N
74 transaction.atomic() # django.db.transaction.Atomic class Atomic(ContextDecorator): def __enter__(self): connection = get_connection(self.using) if not connection.in_atomic_block: # Reset state when entering an outermost atomic block. connection.commit_on_exit = True connection.needs_rollback = False if not connection.get_autocommit(): connection.in_atomic_block = True connection.commit_on_exit = False if connection.in_atomic_block: if self.savepoint and not connection.needs_rollback: sid = connection.savepoint() connection.savepoint_ids.append(sid) else: connection.savepoint_ids.append(None) else: connection.set_autocommit(False, force_begin_transaction_with_broken_autocommit=True) connection.in_atomic_block = True
75 transaction.atomic() # django.db.transaction.Atomic class Atomic(ContextDecorator): def __enter__(self): connection = get_connection(self.using) if not connection.in_atomic_block: # Reset state when entering an outermost atomic block. connection.commit_on_exit = True connection.needs_rollback = False if not connection.get_autocommit(): connection.in_atomic_block = True connection.commit_on_exit = False if connection.in_atomic_block: if self.savepoint and not connection.needs_rollback: sid = connection.savepoint() connection.savepoint_ids.append(sid) else: connection.savepoint_ids.append(None) else: connection.set_autocommit(False, force_begin_transaction_with_broken_autocommit=True) connection.in_atomic_block = True DBとのコネクションをラップした DatabaseWrapperにin_atomic_blockフラグを⽴て autocommitをFalseにする
78 transaction.atomic() # django.core.handlers.base.BaseHandler#make_view_atomic def make_view_atomic(self, view): non_atomic_requests = getattr(view, '_non_atomic_requests', set()) for db in connections.all(): if db.settings_dict['ATOMIC_REQUESTS'] and db.alias not in non_atomic_requests: view = transaction.atomic(using=db.alias)(view) return view non_atomic_requestsに指定してないViewは transaction.atomic()で全体をラップして処理
86 Savepoint # django.db.transaction.Atomic class Atomic(ContextDecorator): def __enter__(self): connection = get_connection(self.using) if not connection.in_atomic_block: # Reset state when entering an outermost atomic block. connection.commit_on_exit = True connection.needs_rollback = False if not connection.get_autocommit(): connection.in_atomic_block = True connection.commit_on_exit = False if connection.in_atomic_block: if self.savepoint and not connection.needs_rollback: sid = connection.savepoint() connection.savepoint_ids.append(sid) else: connection.savepoint_ids.append(None) else: connection.set_autocommit(False, force_begin_transaction_with_broken_autocommit=True) connection.in_atomic_block = True 2回⽬以降に呼ばれたなら、savepointを発⾏ その識別⼦をリスト(スタック)に保持していく
132 Celeryとトランザクション # django.db.backends.base.base.BaseDatabaseWrapper#on_commit def on_commit(self, func): if self.in_atomic_block: # Transaction in progress; save for execution on commit. self.run_on_commit.append((set(self.savepoint_ids), func)) elif not self.get_autocommit(): raise TransactionManagementError('on_commit() cannot be used in manual transaction management') else: # No transaction in progress and in autocommit mode; execute # immediately. func()
133 Celeryとトランザクション # django.db.backends.base.base.BaseDatabaseWrapper#on_commit def on_commit(self, func): if self.in_atomic_block: # Transaction in progress; save for execution on commit. self.run_on_commit.append((set(self.savepoint_ids), func)) elif not self.get_autocommit(): raise TransactionManagementError('on_commit() cannot be used in manual transaction management') else: # No transaction in progress and in autocommit mode; execute # immediately. func()