perf: chain db transactions (#33004)
* perf: chain transactions Frequently used rollback/commits can be modified to chain previous transaction. This reduces one query to DB in most requests. * perf: chain transactions in requests
This commit is contained in:
parent
c2dbae3ece
commit
b57eb60486
3 changed files with 19 additions and 13 deletions
|
|
@ -128,7 +128,7 @@ def application(request: Request):
|
|||
except Exception as e:
|
||||
response = e.get_response(request.environ) if isinstance(e, HTTPException) else handle_exception(e)
|
||||
if db := getattr(frappe.local, "db", None):
|
||||
db.rollback()
|
||||
db.rollback(chain=True)
|
||||
|
||||
else:
|
||||
sync_database()
|
||||
|
|
@ -398,9 +398,9 @@ def sync_database():
|
|||
|
||||
# if HTTP method would change server state, commit if necessary
|
||||
if frappe.local.request.method in UNSAFE_HTTP_METHODS or frappe.local.flags.commit:
|
||||
db.commit()
|
||||
db.commit(chain=True)
|
||||
else:
|
||||
db.rollback()
|
||||
db.rollback(chain=True)
|
||||
|
||||
# update session
|
||||
if session := getattr(frappe.local, "session_obj", None):
|
||||
|
|
|
|||
|
|
@ -1147,7 +1147,7 @@ class Database:
|
|||
mode = "READ ONLY" if read_only else ""
|
||||
self.sql(f"START TRANSACTION {mode}")
|
||||
|
||||
def commit(self):
|
||||
def commit(self, *, chain=False):
|
||||
"""Commit current transaction. Calls SQL `COMMIT`."""
|
||||
if self._disable_transaction_control:
|
||||
warnings.warn(message=TRANSACTION_DISABLED_MSG, stacklevel=2)
|
||||
|
|
@ -1158,12 +1158,15 @@ class Database:
|
|||
|
||||
self.before_commit.run()
|
||||
|
||||
self.sql("commit")
|
||||
self.begin() # explicitly start a new transaction
|
||||
if chain:
|
||||
self.sql("commit and chain")
|
||||
else:
|
||||
self.sql("commit")
|
||||
self.begin()
|
||||
|
||||
self.after_commit.run()
|
||||
|
||||
def rollback(self, *, save_point=None):
|
||||
def rollback(self, *, save_point=None, chain=False):
|
||||
"""`ROLLBACK` current transaction. Optionally rollback to a known save_point."""
|
||||
if save_point:
|
||||
self.sql(f"rollback to savepoint {save_point}")
|
||||
|
|
@ -1173,8 +1176,11 @@ class Database:
|
|||
|
||||
self.before_rollback.run()
|
||||
|
||||
self.sql("rollback")
|
||||
self.begin()
|
||||
if chain:
|
||||
self.sql("rollback and chain")
|
||||
else:
|
||||
self.sql("rollback")
|
||||
self.begin()
|
||||
|
||||
self.after_rollback.run()
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True,
|
|||
retval = method(**kwargs)
|
||||
|
||||
except (frappe.db.InternalError, frappe.RetryBackgroundJobError) as e:
|
||||
frappe.db.rollback()
|
||||
frappe.db.rollback(chain=True)
|
||||
|
||||
if retry < 5 and (
|
||||
isinstance(e, frappe.RetryBackgroundJobError)
|
||||
|
|
@ -293,15 +293,15 @@ def execute_job(site, method, event, job_name, kwargs, user=None, is_async=True,
|
|||
raise
|
||||
|
||||
except Exception as e:
|
||||
frappe.db.rollback()
|
||||
frappe.db.rollback(chain=True)
|
||||
frappe.log_error(title=method_name)
|
||||
frappe.monitor.add_data_to_monitor(exception=e.__class__.__name__)
|
||||
frappe.db.commit()
|
||||
frappe.db.commit(chain=True)
|
||||
print(frappe.get_traceback())
|
||||
raise
|
||||
|
||||
else:
|
||||
frappe.db.commit()
|
||||
frappe.db.commit(chain=True)
|
||||
return retval
|
||||
|
||||
finally:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue