From 26f30cacf523de798b74e2dd7a9c5a587aa26770 Mon Sep 17 00:00:00 2001 From: echel0n Date: Thu, 5 Jun 2014 12:52:30 -0700 Subject: [PATCH 1/2] db lock issues fix test --- sickbeard/db.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/sickbeard/db.py b/sickbeard/db.py index 524a0a65..016e4e96 100644 --- a/sickbeard/db.py +++ b/sickbeard/db.py @@ -20,16 +20,17 @@ from __future__ import with_statement import os.path import re -import threading import sqlite3 import time -import sickbeard +import threading -from sqlalchemy import create_engine, exc +import sickbeard from sickbeard import encodingKludge as ek from sickbeard import logger from sickbeard.exceptions import ex +from sickbeard.common import cpu_presets +from itertools import ifilter db_lock = threading.Lock() @@ -51,9 +52,6 @@ class DBConnection: def __init__(self, filename="sickbeard.db", suffix=None, row_type=None): self.filename = filename - - #engine = create_engine('sqlite:///' + dbFilename(filename)) - #self.connection = engine.connect() self.connection = sqlite3.connect(dbFilename(filename), 20) if row_type == "dict": self.connection.row_factory = self._dict_factory @@ -65,7 +63,7 @@ class DBConnection: try: result = self.select("SELECT db_version FROM db_version") - except exc.OperationalError, e: + except sqlite3.OperationalError, e: if "no such table: db_version" in e.args[0]: return 0 @@ -103,7 +101,7 @@ class DBConnection: if "unable to open database file" in e.args[0] or "database is locked" in e.args[0]: logger.log(u"DB error: " + ex(e), logger.WARNING) attempt += 1 - time.sleep(1) + time.sleep(0.02) else: logger.log(u"DB error: " + ex(e), logger.ERROR) raise @@ -125,8 +123,13 @@ class DBConnection: sqlResult = [] attempt = 0 + # Transaction + self.connection.isolation_level = 'EXCLUSIVE' + self.connection.execute('BEGIN EXCLUSIVE') + while attempt < 5: try: + for qu in querylist: if len(qu) == 1: if logTransaction: @@ -138,6 +141,7 @@ class DBConnection: sqlResult.append(self.connection.execute(qu[0], qu[1])) self.connection.commit() + logger.log(u"Transaction with " + str(len(querylist)) + u" queries executed", logger.DEBUG) return sqlResult except sqlite3.OperationalError, e: @@ -147,7 +151,7 @@ class DBConnection: if "unable to open database file" in e.args[0] or "database is locked" in e.args[0]: logger.log(u"DB error: " + ex(e), logger.WARNING) attempt += 1 - time.sleep(1) + time.sleep(0.02) else: logger.log(u"DB error: " + ex(e), logger.ERROR) raise @@ -178,13 +182,14 @@ class DBConnection: else: logger.log(self.filename + ": " + query + " with args " + str(args), logger.DB) sqlResult = self.connection.execute(query, args) + self.connection.commit() # get out of the connection attempt loop since we were successful break except sqlite3.OperationalError, e: if "unable to open database file" in e.args[0] or "database is locked" in e.args[0]: logger.log(u"DB error: " + ex(e), logger.WARNING) attempt += 1 - time.sleep(1) + time.sleep(0.02) else: logger.log(u"DB error: " + ex(e), logger.ERROR) raise @@ -213,7 +218,7 @@ class DBConnection: query = "UPDATE " + tableName + " SET " + ", ".join(genParams(valueDict)) + " WHERE " + " AND ".join( genParams(keyDict)) - result = self.action(query, valueDict.values() + keyDict.values()) + self.action(query, valueDict.values() + keyDict.values()) if self.connection.total_changes == changesBefore: query = "INSERT INTO " + tableName + " (" + ", ".join(valueDict.keys() + keyDict.keys()) + ")" + \ @@ -238,6 +243,7 @@ class DBConnection: def hasTable(self, tableName): return len(self.action("SELECT 1 FROM sqlite_master WHERE name = ?;", (tableName, )).fetchall()) > 0 + def sanityCheckDatabase(connection, sanity_check): sanity_check(connection).check() @@ -249,6 +255,7 @@ class DBSanityCheck(object): def check(self): pass + # =============== # = Upgrade API = # =============== @@ -269,7 +276,7 @@ def _processUpgrade(connection, upgradeClass): logger.log(u"Database upgrade required: " + prettyName(upgradeClass.__name__), logger.MESSAGE) try: instance.execute() - except exc.DatabaseError, e: + except sqlite3.DatabaseError, e: print "Error in " + str(upgradeClass.__name__) + ": " + ex(e) raise logger.log(upgradeClass.__name__ + " upgrade completed", logger.DEBUG) From 385bf3987ed77128f6f0a7b48cff9b67fcdc8b00 Mon Sep 17 00:00:00 2001 From: echel0n Date: Thu, 5 Jun 2014 12:59:17 -0700 Subject: [PATCH 2/2] db locking issues fix #2 --- sickbeard/db.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sickbeard/db.py b/sickbeard/db.py index 016e4e96..2819d806 100644 --- a/sickbeard/db.py +++ b/sickbeard/db.py @@ -124,8 +124,8 @@ class DBConnection: attempt = 0 # Transaction - self.connection.isolation_level = 'EXCLUSIVE' - self.connection.execute('BEGIN EXCLUSIVE') + self.connection.isolation_level = None + self.connection.execute('BEGIN') while attempt < 5: try: