使用 Teradata 和 SQLAlchemy 避免死锁
Avoid Deadlocks Using Teradata and SQLAlchemy
我正在使用 sqlalchemy 和 sqlalchemy-teradata 查询我的数据库。 sqlalchemy 生成的每个 select 语句都会生成一个 table 锁,这会影响其他无法在 [=38= 上执行任何插入、更新或删除操作的并发用户] 而前一个用户正在阅读它。为了避免这种 table 锁定,我需要在 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,
'[25000] [Teradata][ODBC Teradata Driver][Teradata Database] Only an
ET or null statement is legal after a DDL Statement. ') [SQL: 'SELECT
columnname, columntype, columnlength, chartype, decimaltotaldigits,
decimalfractionaldigits, columnformat, nullable, defaultvalue,
idcoltype \nFROM dbc.ColumnsV \nWHERE DatabaseName=? AND TableName=?']
[parameters: ('dev_migration_tool', 'migration_object_type')]
连接到 Teradata 时,我添加了 dnoeth 在上面的评论中提供的声明。请注意,在 ANSI-mode 会话中, SET SESSION
被视为 DDL 语句,必须提交。需要以下内容以避免在上面的初始 post 中触发的错误消息: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()
我正在使用 sqlalchemy 和 sqlalchemy-teradata 查询我的数据库。 sqlalchemy 生成的每个 select 语句都会生成一个 table 锁,这会影响其他无法在 [=38= 上执行任何插入、更新或删除操作的并发用户] 而前一个用户正在阅读它。为了避免这种 table 锁定,我需要在 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, '[25000] [Teradata][ODBC Teradata Driver][Teradata Database] Only an ET or null statement is legal after a DDL Statement. ') [SQL: 'SELECT columnname, columntype, columnlength, chartype, decimaltotaldigits, decimalfractionaldigits, columnformat, nullable, defaultvalue, idcoltype \nFROM dbc.ColumnsV \nWHERE DatabaseName=? AND TableName=?'] [parameters: ('dev_migration_tool', 'migration_object_type')]
连接到 Teradata 时,我添加了 dnoeth 在上面的评论中提供的声明。请注意,在 ANSI-mode 会话中, SET SESSION
被视为 DDL 语句,必须提交。需要以下内容以避免在上面的初始 post 中触发的错误消息: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()