我在使用 SQLite3 数据库读取数据时遇到一些问题。
背景: 我构建了一个 python 程序,它依赖于两个并行运行的脚本:
从大量谷歌搜索/阅读论坛主题和 SQLite 文档中,我相信这是由于以下事实:当 script1 写入数据库 1 的表 1 时,表 1 被阻止访问。当 script2 的进程与 script1 在同一个数据库表 1 上的写入重合时,这就会成为问题。我注意到,当我只运行 script2 (而不执行 script1)时,我从来没有遇到过这个问题(即从 script2 读取 table1 的所有操作都不会被跳过),并且所有过程都运行顺利。
我尝试了很多事情,包括为我的数据库连接添加超时和pragma busy超时(下面的片段)。两个超时都已应用于我在两个脚本中使用的所有数据库函数,但结果是相同的。
def db_function1(param1,param2,param3):
con=None
temp_df='null'
db=os.path.join(os.getcwd(), './database1.db')
try:
con=sqlite3.connect(db, timeout=20) #Increase timeout from default 5sec.
c = con.cursor()
c.execute('''pragma busy_timeout=10000''') #Busy timeout changed to 10s (in ms)
temp_df = pd.read_sql(
'''SELECT * FROM table1 WHERE .....''' #I skipped the query detail to make this block neater to read
% (param1,param2,param3), con)
con.close()
except Error as e:
print(e)
return temp_df
进一步阅读https://www.sqlite.org/faq.html#q5,似乎前进的道路是使用 sqlite3_busy_handler() 或 sqlite3_busy_timeout() 来运行测试,如果表实际上很忙,那么它可以等待并重试(通过在繁忙时暂停依赖于 table1 读取的 script1 进程几秒钟),但我无法让它工作或在网上找到任何应用程序示例。
有什么想法吗?
谢谢!
如果没有可重现的问题,很难给出明确的答案。但是,请测试一下它是否可以解决您的问题。我包含了一个 custom_busy_handler 函数,它将返回繁忙处理程序的回调函数和一个 inner_callback,它是 SQLite 遇到繁忙情况时将调用的实际回调。
它会休眠指定的超时时间,并返回 True 重试或返回 False 放弃。 db_function1 已修改为使用 con.set_busy_handler(custom_busy_handler(retries, timeout)) 设置自定义繁忙处理程序。尝试一下重试和超时参数,看看它在您的具体情况下如何工作
def custom_busy_handler(retries, timeout):
def inner_callback(tries):
if tries >= retries:
return False # Give up if retries exceed a certain limit
time.sleep(timeout)
return True
return inner_callback
def db_function1(param1, param2, param3, retries=5, timeout=1):
con = None
temp_df = 'null'
db = os.path.join(os.getcwd(), './database1.db')
try:
con = sqlite3.connect(db, timeout=20) # Increase timeout from default 5sec.
con.execute('''pragma busy_timeout=10000''') # Busy timeout changed to 10s (in ms)
# Set up a custom busy handler
con.set_busy_handler(custom_busy_handler(retries, timeout))
temp_df = pd.read_sql(
'''SELECT * FROM table1 WHERE ...''',
% (param1, param2, param3), con)
con.close()
except Error as e:
print(e)
return temp_df
# Example of using db_function1 with custom busy handler
result = db_function1("value1", "value2", "value3", retries=5, timeout=1)
print(result)