On Dec 6, 2007, at 8:57 AM, imgrey wrote:
> >> i can only make comments about fragments like this but i cant address >> your full design issue since you havent supplied a fully working >> illustration of what it is youre trying to do. > > > the daemon: http://dpaste.com/hold/27089/ > and required utils.py modele: http://dpaste.com/hold/27092/ > > it was running with revision 3863 OK, your Watch class is procesing events as they occur. a particular event is bounded by the run() method of the watch class; the reasonable place for you to create/destroy a Session is at the boundaries of handling those events - so "arrange" should open a session at the start of its run() method, and close() it at the end. the scope of transaction should also be bordered by the run() method. if you want to keep using scoped_session(), thats fine, but i think you need to understand what that means if you are going to use it. I see you have lock.acquire() and lock.release() pairs around every usage of the session - this doesn't do anything since the scoped_session is a "thread local" manager of sessions (it might achieve some locking against concurrent database access but database locks, but not really very well the way its laid out). heres a wikipedia article on "threadlocal": http://en.wikipedia.org/wiki/Thread-local_storage . your app is currently using a unique Session for every thread because you have configured scoped_session(). Theres nothing wrong with using scoped_session(), it means that the start of run() would say, Session(), to open a new session, and the end would say Session.close(), to close it out, release connections/ transactions, etc. This lifespan is described here: http://www.sqlalchemy.org/docs/04/session.html#unitofwork_contextual_lifespan >> > > How to open one session for all threads ? Using Lock with inserts/ > updates should help in this case, right ? you dont want to open one session for all threads. the session itself is not threadsafe (read the last item) : http://www.sqlalchemy.org/docs/04/session.html#unitofwork_using_faq . Theres no reasonable reason you'd want to share a session among threads, unless you are trying to use it as a cache. if you are trying to use it as a cache for many threads, this is not its intended purpose; id recommend using a plain dict or memcached for that instead. also id get the whole app to work completely before adding any caching. Also, its not typical to have one transaction/connection shared among threads either. if thats what youre trying to go for here, and thats why you have all the locking going on, that implies your app would just have one database connection in total. if you wanted to do that, then bind the session like this: the_one_connection = engine.connect() sess = Session(bind=the_one_connection) then youd have many sessions all commuicating to the same underlying connection. im not sure how well psycopg2 allows multiple threads to use a single connection (you certainly dont want to do it with mysqldb....). but id recommend going for a transaction-per-event approach instead. > > I was trying to represent this SQL statement in ORM: "DELETE FROM > fs_file WHERE path='/' and user_id=<theone.id>". If I'd need to delete > user I'll use session.query.delete(user), indeed. But how to perform > writing operations in proper way then, without execute() ? I was > looking, thinking, asking and thinking again but came to nithing yet ) if you had already looked up the Path with those attributes, and you have a Path instance, you can just session.delete(mypath). If not, then sure just issue the DELETE. as far as the SELECTs, if you issue your SELECT like this: SELECT * from file where path='/' AND user_id=id FOR UPDATE within a transaction, that statement will lock those rows explicitly against other transactions doing the exact same thing (i.e. they say FOR UPDATE also). Then, if you want to delete those rows: DELETE from file where path='/' AND user_id=id; COMMIT; the other transaction then wakes up after the first one issues COMMIT; its SELECT ..FOR UPDATE returns zero rows because the row was deleted (or it returns whatever rows still remain). this is generally how you should be achieving your locking against individual "file" records. if youd like to select using the Session with this method, use session.query(cls).with_lockmode('update').filter(...).first() . watch your SQL echoing and youll see it do a SELECT..FOR UPDATE in every case, locking every row it touches against other sessions also using FOR UPDATE. when that session is done working, commit() and close() it. one of the other sleeping transactions will wake up and do whatever it wanted to do. it seems like your arrange() method is generally SELECTing rows which are later deleted within LockingManager. I think if you used FOR UPDATE appropriately, that should handle all the locking requirements. I dont think you'd need any thread mutexing in the application in this case (unless you started adding a cache; access to a global cache should be mutexed). > > But I see that sqlalchemy beginning transaction anyway just gives you more explicit control, if you wanted it > > session != transaction ? the difference between them is presence in > session of cache ? just give the whole Session page a good read: http://www.sqlalchemy.org/docs/04/session.html as an alternative introduction you can also read Hibernate's session page, 90% of this applies to the SQLAlchemy session including optimistic/pessimistic concurrency: http://www.hibernate.org/hib_docs/v3/reference/en/html/transactions.html --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---