RE: [cx-oracle-users] Creating a large number of database connections
Brought to you by:
atuining
From: Anthony T. <an...@co...> - 2004-01-15 17:26:37
|
On Thu, 2004-01-15 at 09:32, Moore, Paul wrote: > From: Anthony Tuininga [mailto:an...@co...] > > Could you explain about the "cursors only used from a single > > thread" problem is? > > Sorry. Basically, I'm running a query against lots of databases, > and storing the results in a central database. So I have a single > connection to the central DB, against which I'm running a series > of inserts. Ok, that makes sense now. :-) > Hmm, maybe I should be sharing the central *connection* between > the multiple threads, and creating individual cursors to do the > inserts on a per-thread basis. Is that OK? (Am I reading the > documentation right that I can share a connection, but not a > cursor?) Yes, you can share the connection, but don't try sharing a cursor, unless you like segfaults, of course. :-) > > > I am assuming here that you have one connection per > > thread and therefore one cursor per thread so there shouldn't > > be a problem here, right? > > It's passing the data back to a central update thread that hurts. > Mucking about with queues, knowing when the threads have completed, > etc :-( Although you __can__ create a separate cursor for each thread and perform the insert in each separate thread, if you have a large number of them, this can hurt you. At that point, the queue will work in your favor because the prepare() phase can be skipped. The difference is probably a few milliseconds per thread so it is significantly smaller than the connection overhead (at least 35 ms). Your call. :-) > > This code: > [...] > > will definitely be slower than this code: > > > def PerformQuery(db): > > connection = cx_Oracle.connect("user", "pw", db) > > cursor = connection.cursor() > > cursor.execute("some_query") > > > for db in listOfDbs: > > thread = thread.start_new_thread(PerformQuery, (db,)) > > > Of course, you need to add synchronization code which is completely > > missing but I can help you with that, if needed. I've written a few > > threaded programs and I know the pitfalls that can suddenly open up > > beneath your feet. :-) > > Thanks for the offer. I've managed to find a lot of thread pitfalls > myself :-) They're amazingly easy to find, eh? That's why I've written a few simple classes to manage such things as queues and the like so that I don't have to think about it each time. :-) > How likely is the following sketch to work? (I'll try it, but one of > the things I have learned is that running a threaded program twice > exposes two different sets of bugs :-)) > > cx_Oracle.OPT_Threading = 1 # I think I need this? Yes, you definitely need this. Without it, your program will crash and burn rather quickly. It turns on Oracle threading mode. I've considered making this a part of the connect() method but it really does need to be global. Perhaps another method might make it more clear. Something like this, perhaps? cx_Oracle.setthreaded() Any thoughts on that? > def PerformQuery(db, cn): > connection = cx_Oracle.connect("user", "pw", db) > cursor = connection.cursor() > cursor.execute("some_query") > ins = cn.cursor() > insert_data = process(cursor.fetchall()) > ins.executemany("insert_sql", insert_data) > > cn = cx_Oracle.connect("user", "pw", "centraldb") > threadlist = [] > for db in listOfDbs: > thread = thread.start_new_thread(PerformQuery, (db, cn)) > threadlist.append(thread) > > for thread in threadlist: > thread.join() > > cn.commit() > cn.close() Yes, this should work. Of course, you might want to decide whether you want to use the threading module or the thread module and then make the necessary changes. :-) > Paul -- Anthony Tuininga an...@co... Computronix Distinctive Software. Real People. Suite 200, 10216 - 124 Street NW Edmonton, AB, Canada T5N 4A3 Phone: (780) 454-3700 Fax: (780) 454-3838 http://www.computronix.com |