2

トランザクションが終了するまで行がロックされるように、テーブル内の一連の行をSELECTFORSHAREしようとしています。SQLAlchemy 0.7.9を使用して、PostgreSQL9.1.6データベースでこれを実行しています。これは問題のPythonコードです:

NUM_TERMS = 10
conn = engine.connect()
get_terms = select([search_terms.c.term_id, search_terms.c.term],
                   and_(search_terms.c.lock==False,
                   search_terms.c.status==False),
                   order_by=search_terms.c.term,
                   limit=NUM_TERMS, for_update="read")
trans = conn.begin()
try:
    search_terms = conn.execute(get_terms).fetchall()
    for term in search_terms:
        lock_terms = update(search_terms).\
                     where(search_terms.c.term_id==term.term_id).\
                     values(lock=True)
        conn.execute(lock_terms)
    if trans.commit():
        <do things with the search terms>
except:
    trans.rollback()

問題は、上記の選択コードによって生成されたSQLクエリがFOR SHAREではなく、FORUPDATEであるということです。

SELECT search_terms.term_id, search_terms.term
FROM search_terms
WHERE search_terms.lock = :lock_1 AND search_terms.status = :status_1     
ORDER BY search_terms.term
LIMIT :param_1 FOR UPDATE

SQLAlchemy APIのドキュメントによると、「for_update」パラメータの説明の下にあります。

Postgresql方言では、値「read」と「read_nowait」はそれぞれFORSHAREとFORSHARENOWAITに変換されます。

上記によると、コンパイルされたSQLステートメントはFOR SHAREである必要がありますが、そうではありません。私のコードのエラーはどこにありますか?

4

1 に答える 1

1

再現できません:

from sqlalchemy import *

m = MetaData()
t = Table('t', m, Column('x', Integer))

s = select([t], for_update="read")

from sqlalchemy.dialects import postgresql
print s.compile(dialect=postgresql.dialect())

e = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
with e.begin() as conn:
    m.create_all(conn)
    conn.execute(s)

出力は、スタンドアロン コンパイルとしても Postgresql 会話内でも、FOR SHARE を取得することを示しています。0.7.9 および 0.8.0b2 でテスト済み。完全に実行可能なテスト ケースを提供できる場合は、より多くの光を当てる可能性があります。

SELECT t.x 
FROM t FOR SHARE
2012-12-20 23:53:33,670 INFO sqlalchemy.engine.base.Engine select version()
2012-12-20 23:53:33,671 INFO sqlalchemy.engine.base.Engine {}
2012-12-20 23:53:33,672 INFO sqlalchemy.engine.base.Engine select current_schema()
2012-12-20 23:53:33,672 INFO sqlalchemy.engine.base.Engine {}
2012-12-20 23:53:33,674 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2012-12-20 23:53:33,674 INFO sqlalchemy.engine.base.Engine select relname from pg_class c join pg_namespace n on n.oid=c.relnamespace where n.nspname=current_schema() and relname=%(name)s
2012-12-20 23:53:33,675 INFO sqlalchemy.engine.base.Engine {'name': u't'}
2012-12-20 23:53:33,676 INFO sqlalchemy.engine.base.Engine SELECT t.x 
FROM t FOR SHARE
2012-12-20 23:53:33,676 INFO sqlalchemy.engine.base.Engine {}
2012-12-20 23:53:33,676 INFO sqlalchemy.engine.base.Engine COMMIT
于 2012-12-21T04:57:44.057 に答える