使用Teradata和SQLAlchemy避免死锁

时间:2018-04-02 11:52:45

标签: python sqlalchemy teradata

我使用 sqlalchemy sqlalchemy-teradata 来查询我的数据库。由 sqlalchemy 生成的每个select语句都会生成一个表锁,这会影响其他并发用户,这些用户在上一个用户正在读取它时无法对表执行任何插入,更新或删除操作。为了避免这种表锁,我需要在<{strong> SELECT语句之前添加以下字符串

LOCK ROW FOR ACCESS
SELECT * FROM DATABASE.TABLE;

如何覆盖sqlalchemy select语句来添加此字符串? 请注意,我还在GitHub上提出了这个问题,但到目前为止还没有找到任何解决方案:https://github.com/Teradata/sqlalchemy-teradata/issues/39

[更新]

连接到Teradata时,我添加了以下由dnoeth提供的声明:

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
from sqlalchemy.orm import scoped_session, sessionmaker
[...]
engine = create_engine('teradata://' + user + ':' + password + '@' + host + ':22/' + database)
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
db_session.execute('SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;')  # To avoid locking tables when doing select on tables

Base = declarative_base(cls=DeferredReflection)
Base.query = db_session.query_property()

但是现在我在SQLAlchemy尝试读取Teradata元数据时出现以下错误消息:

  

sqlalchemy.exc.DatabaseError:(teradata.api.DatabaseError)(3932,   &#39; [25000] [Teradata] [ODBC Teradata驱动程序] [Teradata数据库]仅限一个   在DDL声明之后,ET或null语句是合法的。 &#39;)[SQL:&#39; SELECT   columnname,columntype,columnlength,chartype,decimaltotaldigits,   decimalfractionaldigits,columnformat,nullable,defaultvalue,   idcoltype \ nFROM dbc.ColumnsV \ nWHERE DatabaseName =? AND TableName =?&#39;]   [参数:(&#39; dev_migration_tool&#39;,&#39; migration_object_type&#39;)]

1 个答案:

答案 0 :(得分:0)

连接到Teradata时,我添加了dnoeth上面评论中提供的声明。请注意,在ANSI模式会话中,SET SESSION被视为DDL语句,必须提交。需要执行以下操作以避免在上面的初始帖子中触发的错误消息:db_session.commit()

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base, DeferredReflection
from sqlalchemy.orm import scoped_session, sessionmaker
[...]
engine = create_engine('teradata://' + user + ':' + password + '@' + host + ':22/' + database)
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
db_session.execute('SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;')  # To avoid locking tables when doing select on tables
db_session.commit()

Base = declarative_base(cls=DeferredReflection)
Base.query = db_session.query_property()