Hello, I have a problem with "SELECT ... FOR UPDATE;" command.
I have a MySQL database, table created with TYPE=INNODB engine specification with proper transaction isolation level set. I want to issue "SELECT ... FOR UPDATE;" command to lock specific row of table for updates. Here's a sample script: # -*- coding: cp1251 -*- import sqlalchemy import time import sys databaseParams = { \ 'echo': True, 'echo_uow': True, 'logger': file( 'sql.log', 'w' ), 'convert_unicode': True,} engine = sqlalchemy.create_engine( 'mysql', { 'db':'vasilytest', 'user':'root', 'passwd':'', 'host':'127.0.0.1' }, **databaseParams ) contragents = sqlalchemy.Table( 'contragents', engine, sqlalchemy.Column( 'id', sqlalchemy.Integer, primary_key=True ), sqlalchemy.Column( 'first_name', sqlalchemy.String(50), default='', key='firstName' ), sqlalchemy.Column( 'last_name', sqlalchemy.String(50), default='', key='lastName' ), sqlalchemy.Column( 'patronymic', sqlalchemy.String(50) ), default='', mysql_engine='INNODB' ) if 'create' in sys.argv: contragents.create() class SqlStrMixing( object ): def __str__( self ): s = [ self.__class__.__name__ + ': ' ] for c in self.c: s.append( '%s=%s ' % ( c.key, getattr(self, c.key) ) ) return ''.join(s).encode('cp866') class Contragent(SqlStrMixing): pass sqlalchemy.assign_mapper( Contragent, contragents ) session = sqlalchemy.objectstore.Session() session.begin() obj = Contragent.mapper.using(session).select(Contragent.c.id==17, for_update=True)[0] print obj time.sleep(20) session.commit() sqlalchemy.objectstore.commit() I launch first copy of this script and it immediatlely prints selected object and sleeps for 20 seconds. Then I launch second copy of script and it immediately prints selected object too. That's wrong, it should block and wait for first script to commit transaction. When I inspect sql.log I see following: SELECT contragents.patronymic [skiped for clarity] contragents.first_name AS contragents_first_name FROM contragents WHERE contragents.id = %s FOR UPDATE[17] i.e. right SQL command, but selected row doesn't lock. Perhaps I am doing something wrong with transactions. Can anyone explain what's going on? And how to achieve desired behaviour? And maybee there's another way to lock row of table for update? I did the same using regular DB-API and it worked as expected. Here's source code: # -*- coding: cp1251 -*- import MySQLdb as dbms import time params = { \ 'host': '127.0.0.1', 'user': 'root', 'db' : 'vasilytest', 'passwd': '' } db = dbms.Connect( **params ) cursor = db.cursor() cursor.execute( """select * from contragents where id=17 for update;""" ) print cursor.fetchall() time.sleep(20) db.commit() I launch first copy of this script and it immediately prints fetched columns and sleeps for 20 seconds. Then I launch second copy of the script and it blocks untill first script commits or interrupted (using Ctrl-C or something), i.e. desired behaviour. -- Best regards, Vasily ------------------------------------------------------- This SF.Net email is sponsored by xPML, a groundbreaking scripting language that extends applications into web and mobile media. Attend the live webcast and join the prime developer group breaking into this new coding territory! http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642 _______________________________________________ Sqlalchemy-users mailing list Sqlalchemy-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users