Try fix Recursive use of cursors ProgrammingError by creating new cursor for every execute and move Lock to db

This commit is contained in:
shortcutme 2019-11-27 03:07:08 +01:00
parent afd23849a6
commit fca9db7972
No known key found for this signature in database
GPG key ID: 5B63BAE6CB9613AE
6 changed files with 51 additions and 27 deletions

View file

@ -8,6 +8,7 @@ import atexit
import sys
import gevent
from gevent._threading import Lock
from Debug import Debug
from .DbCursor import DbCursor
@ -44,15 +45,18 @@ def dbCloseAll():
for db in opened_dbs[:]:
db.close()
gevent.spawn(dbCleanup)
gevent.spawn(dbCommitCheck)
atexit.register(dbCloseAll)
class DbTableError(Exception):
def __init__(self, message, table):
super().__init__(message)
self.table = table
class Db(object):
def __init__(self, schema, db_path, close_idle=False):
@ -76,6 +80,7 @@ class Db(object):
self.last_query_time = time.time()
self.last_sleep_time = time.time()
self.num_execute_since_sleep = 0
self.lock = Lock()
def __repr__(self):
return "<Db#%s:%s close_idle:%s>" % (id(self), self.db_path, self.close_idle)
@ -278,7 +283,6 @@ class Db(object):
except Exception as err:
self.log.error("Error creating table %s: %s" % (table_name, Debug.formatException(err)))
raise DbTableError(err, table_name)
#return False
self.log.debug("Db check done in %.3fs, changed tables: %s" % (time.time() - s, changed_tables))
if changed_tables:

View file

@ -1,7 +1,5 @@
import time
import re
import gevent
from gevent._threading import Lock
from util import helper
@ -13,9 +11,7 @@ class DbCursor:
def __init__(self, conn, db):
self.conn = conn
self.db = db
self.cursor = conn.cursor()
self.logging = False
self.lock = Lock()
def quoteValue(self, value):
if type(value) is int:
@ -100,19 +96,20 @@ class DbCursor:
query, params = self.parseQuery(query, params)
s = time.time()
cursor = self.conn.cursor()
try:
self.lock.acquire(True)
self.db.lock.acquire(True)
if params: # Query has parameters
res = self.cursor.execute(query, params)
res = cursor.execute(query, params)
if self.logging:
self.db.log.debug(query + " " + str(params) + " (Done in %.4f)" % (time.time() - s))
else:
res = self.cursor.execute(query)
res = cursor.execute(query)
if self.logging:
self.db.log.debug(query + " (Done in %.4f)" % (time.time() - s))
finally:
self.lock.release()
self.db.lock.release()
# Log query stats
if self.db.collect_stats:
@ -121,12 +118,35 @@ class DbCursor:
self.db.query_stats[query]["call"] += 1
self.db.query_stats[query]["time"] += time.time() - s
if not self.db.need_commit:
query_type = query.split(" ", 1)[0].upper()
if query_type in ["UPDATE", "DELETE", "INSERT", "CREATE"]:
self.db.need_commit = True
query_type = query.split(" ", 1)[0].upper()
is_update_query = query_type in ["UPDATE", "DELETE", "INSERT", "CREATE"]
if not self.db.need_commit and is_update_query:
self.db.need_commit = True
return res
if is_update_query:
return cursor
else:
return res
def executemany(self, query, params):
while self.db.progress_sleeping:
time.sleep(0.1)
self.db.last_query_time = time.time()
s = time.time()
cursor = self.conn.cursor()
try:
self.db.lock.acquire(True)
cursor.executemany(query, params)
finally:
self.db.lock.release()
if self.logging:
self.db.log.debug("%s x %s (Done in %.4f)" % (query, len(params), time.time() - s))
return cursor
# Creates on updates a database row without incrementing the rowid
def insertOrUpdate(self, table, query_sets, query_wheres, oninsert={}):
@ -135,11 +155,11 @@ class DbCursor:
params = query_sets
params.update(query_wheres)
self.execute(
res = self.execute(
"UPDATE %s SET %s WHERE %s" % (table, ", ".join(sql_sets), " AND ".join(sql_wheres)),
params
)
if self.cursor.rowcount == 0:
if res.rowcount == 0:
params.update(oninsert) # Add insert-only fields
self.execute("INSERT INTO %s ?" % table, params)
@ -215,4 +235,4 @@ class DbCursor:
return row
def close(self):
self.cursor.close()
pass