繁体   English   中英

使用cx_Oracle的龙卷风后台任务

[英]Tornado background task using cx_Oracle

我正在使用底层的Tornado框架运行Bokeh服务器。

我需要服务器在某些时候刷新一些数据。 这是通过使用Cx_Oracle从Oracle数据库中获取行来完成的

多亏了Tornado的PeriodicCallback ,该程序每30秒检查一次是否应该加载新数据:

server.start() 
from tornado.ioloop import PeriodicCallback
pcallback = PeriodicCallback(db_obj.reload_data_async, 10 * 1e3)
pcallback.start()
server.io_loop.start()

其中db_obj是一个类的实例,该类负责与DB相关的功能(连接,提取,...)。

基本上,这就是reload_data_async函数的样子:

executor = concurrent.futures.ThreadPoolExecutor(4)

# methods of the db_obj class ...

@gen.coroutine
def reload_data_async(self):
  # ... first, some code to check if the data should be reloaded ...
  # ...
  if data_should_be_reloaded:
    new_data = yield executor.submit(self.fetch_data)

def fetch_data(self):
   """ fetch new data in the DB """
   cursor = cx.Cursor(self.db_connection) 
   cursor.execute("some SQL select request that takes time (select * from ...)")

   rows = cursor.fetchall()
   # some more processing thereafter 
   # ...

基本上,这可行。 但是,当我尝试在将数据加载到fetch_data (通过单击以在GUI中显示)读取数据时,该程序由于竞态条件而崩溃(我猜是吗?):它正在同时获取数据时正在访问数据。

我刚刚发现tornado.concurrent.futures不是线程安全的:

tornado.concurrent.Future与current.futures.Future相似,但不是线程安全的(因此与单线程事件循环一起使用时更快)。

总而言之,我认为我应该创建一个新线程来处理CX_Oracle操作。 我可以使用Tornado并继续使用PerodicCallback函数吗? 如何将异步操作转换为线程安全的? 这是怎么做的?

PS:我正在使用Python 2.7

谢谢

解决了!

@Sraw是正确的:它不会导致崩溃。

说明fetch_data()使用的是cx Oracle Connection对象( self.db_connection ),默认情况下该对象不是线程安全的。 如Cx Oracle文档中所述,将threaded参数设置为True可以用互斥体包装共享连接。

threaded参数应为布尔表达式,该表达式指示Oracle是否应使用互斥体包装对连接的访问​​。 在单线程应用程序中这样做会导致大约10-15%的性能损失,这就是为什么默认值为False的原因。

因此,我在代码中修改了以下内容,当用户尝试在刷新数据时尝试访问数据时,它现在不会崩溃:

# inside the connect method of the db_obj class
self.db_connection = cx.connect('connection string', threaded=True) # False by default

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM