【问题标题】:How to SELECT FOR SHARE using SQLAlchemy with PostgreSQL?如何在 PostgreSQL 中使用 SQLAlchemy 选择 FOR SHARE?
【发布时间】:2012-12-08 14:45:53
【问题描述】:

我正在尝试 SELECT FOR SHARE 表中的一组行,以便它们被锁定直到事务结束。我正在使用 SQLAlchemy 0.7.9 在 PostgreSQL 9.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()

问题是上面select代码生成的SQL查询不是FOR SHARE,是FOR UPDATE:

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 docs,“for_update”参数说明下:

使用 Postgresql 方言,值“read”和“read_nowait”分别转换为 FOR SHARE 和 FOR SHARE NOWAIT。

根据上面,编译好的SQL语句应该是FOR SHARE,其实不是。我的代码哪里出错了?

【问题讨论】:

    标签: python sqlalchemy postgresql-9.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
    

    【讨论】:

      猜你喜欢
      • 2020-04-22
      • 1970-01-01
      • 2020-06-23
      • 2014-06-09
      • 1970-01-01
      • 1970-01-01
      • 2023-04-03
      • 2015-05-04
      • 2023-03-10
      相关资源
      最近更新 更多