我注意到,SQLite db.commit()
(保存到磁盘)在我的小数据库中需要50ms到100ms。这是正常的,而且 载于此但 每次INSERT后,在客户的每次请求后都要做,太麻烦了。 像这样。
import bottle, sqlite3, random
@bottle.route('/')
def index():
c = db.cursor()
c.execute('INSERT INTO test VALUES (?)', (random.randint(0, 10000)))
c.close()
db.commit() # should we do it here? (100ms is too much after *each* request!)
return 'hello'
def worker():
db.commit() # or here? how to call this worker once every 10 seconds?
db = sqlite3.connect('test.db')
db.execute("CREATE TABLE IF NOT EXISTS test (a int)")
bottle.run(port=80)
更准确地说,我不想在每次请求后损失100ms。我优化了我的服务器,让它的服务速度非常快(10ms),如果因为DB提交而损失100ms,那就太可惜了。
当然,我 可以 另起炉灶 worker()
只有每10秒一次(在最坏的情况下,如果应用程序崩溃,只有最后10秒的DB会丢失)。但是我读到不建议使用 线程.
问题:如何在BottleFlask webserver上下文中,每隔几秒就进行一次SQLite DB提交(而不是每次INSERT后进行一次)?
你可以写一个Flask after_request() 处理程序,并在那里提交数据库。你甚至可以限制只有在距离上次提交已经过了一定时间的情况下才这样做。
这样既不会阻止你的请求,也不会过于频繁地保存文件。
下面是一个尝试。它每10秒才提交一次,如果在这个时间段内有insert的话。
注意:它需要 check_same_thread=False
如上所述 ProgrammingError.在线程中创建的SQLite对象只能在同一线程中使用。在一个线程中创建的SQLite对象只能在同一个线程中使用。.
import bottle, sqlite3, random, threading, time
@bottle.route('/')
def index():
global committhread
c = db.cursor()
c.execute('INSERT INTO test VALUES (?)', (random.randint(0, 10000),))
c.close()
if not committhread:
print('Calling commit()...')
committhread = threading.Thread(target=commit)
committhread.start()
else:
print('A commit is already planned.')
return 'hello'
def commit():
global committhread
print("We'll commit in 10 seconds.")
time.sleep(10) # I hope this doesn't block/waste CPU here?
db.commit()
print('Committed.')
committhread = None
db = sqlite3.connect('test.db', check_same_thread=False)
db.execute("CREATE TABLE IF NOT EXISTS test (a int)")
committhread = None
bottle.run(port=80)
但是,正如在下列文件中所讨论的那样: SQLite和Python:最多每10秒提交一次,而不是在每次客户端请求后提交。 在做之前的代码之前,还有一些其他的选项值得尝试,比如。
c.execute('PRAGMA synchronous = OFF')
c.execute('PRAGMA journal_mode = OFF')
这样至少可以提高一个数量级的性能。
有用的资源。