5

当连接对象被不同的线程使用时,cx_Oracle 游标的行为是什么?生成器将如何影响这种行为?具体来说...

编辑:原始示例函数不正确;子函数返回了一个生成器,yield没有直接在循环中使用。这澄清了何时finally执行(之后return执行),但仍然没有回答如果另一个线程开始使用创建游标的连接对象是否可以使用游标。它实际上似乎(至少在 python 2.4 中)try...finallyyield导致语法错误。

def Get()
  conn = pool.get()
  try:
    cursor = conn.cursor()
    cursor.execute("select * from table ...")
    return IterRows(cursor)
  finally:
    pool.put(conn)

def IterRows(cursor):
  for r in cursor:
    yield r

Get()是一个被多个线程调用的函数。连接是使用threaded=False参数创建的。

我在想...

  1. cursor如果线程 2 出现并使用相同的连接对象,线程 1 的对象是否仍然可用?如果没有,可能会发生什么?

我看到的行为是 cx_Oracle 中谈论协议错误的异常,然后是段错误。

4

1 回答 1

2

请参阅文档threadsafety是,我引用,

当前为 2,这意味着线程可以共享模块和连接,但不能共享游标。

因此,您的“游标池”构造(其中一个游标可能由不同的线程使用)似乎超出了该threadsafety级别。这不是共享连接的问题(没关系,因为您已threaded在连接的构造函数中正确传递),而是游标。您可能希望在threading.local线程第一次使用每个游标后将其存储,以便每个线程可以拥有自己的 1 游标“池”(虽然不是关键优化:制作新游标不是繁重的任务手术)。

Wrt你的问题2,finally当生成器对象(通过调用生成器函数构建Get)全部完成时执行该子句 - 因为它正在引发StopIteration,或者因为它正在被垃圾收集(通常是因为对它的最后引用刚刚消失)。例如,如果来电者是:

def imthecaller():
  for i, row in enumerate(Get()):
    print i, row
    if i > 1: break
  # this is the moment the generators' finally-clause runs
  print 'bye'

finally(最多)3 行之后执行yield

于 2010-02-22T06:47:50.833 回答