python - 我可以在没有事务的情况下通过 sqlalchemy 执行查询吗
问题描述
我正在尝试使用 sqlalchemy 在 Mysql 数据库上执行存储过程。
它在 shell 中运行良好,但抛出此错误:
OperationalError: (MySQLdb._exceptions.OperationalError) (1568, "Transaction characteristics can't be changed while a transaction is in progress")
原因似乎是 SQLAlchemy 在事务中运行查询。并且存储过程中的事务与之冲突。以下是 sqlalchemy 日志:
2019-07-24 15:20:28,888 INFO sqlalchemy.engine.base.Engine SHOW VARIABLES LIKE 'sql_mode'
2019-07-24 15:20:28,888 INFO sqlalchemy.engine.base.Engine ()
2019-07-24 15:20:28,900 INFO sqlalchemy.engine.base.Engine SELECT DATABASE()
2019-07-24 15:20:28,900 INFO sqlalchemy.engine.base.Engine ()
2019-07-24 15:20:28,910 INFO sqlalchemy.engine.base.Engine show collation where `Charset` = 'utf8mb4' and `Collation` = 'utf8mb4_bin'
2019-07-24 15:20:28,910 INFO sqlalchemy.engine.base.Engine ()
2019-07-24 15:20:28,916 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS CHAR(60)) AS anon_1
2019-07-24 15:20:28,917 INFO sqlalchemy.engine.base.Engine ()
2019-07-24 15:20:28,923 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS CHAR(60)) AS anon_1
2019-07-24 15:20:28,923 INFO sqlalchemy.engine.base.Engine ()
2019-07-24 15:20:28,928 INFO sqlalchemy.engine.base.Engine SELECT CAST('test collated returns' AS CHAR CHARACTER SET utf8mb4) COLLATE utf8mb4_bin AS anon_1
2019-07-24 15:20:28,928 INFO sqlalchemy.engine.base.Engine ()
2019-07-24 15:20:28,938 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-07-24 15:20:28,938 INFO sqlalchemy.engine.base.Engine CALL my_stored_procedure(params);
2019-07-24 15:20:28,938 INFO sqlalchemy.engine.base.Engine ()
我想知道的是我是否可以在没有事务的情况下从 sqlalchemy 运行查询。或者有没有其他方法可以解决问题。我尝试更改存储过程的隔离级别,但这会导致表锁定问题。
解决方案
SQLAlchemy 总是尝试在事务中执行查询。COMMIT
但是,可以通过执行语句轻松结束事务。
首先,你需要一个连接。然后使用该连接发出一个COMMIT
,这将结束新启动的事务。
这是一个尝试创建新数据库的示例代码,在事务内部运行时会引发错误。我正在使用 postgres,但使用 MySQL 的相同逻辑也适用。尝试在事务中创建新数据库:
from sqlalchemy import create_engine
# replace URL with your MySQL instance
db_url = "postgresql://postgres:secure_pass@localhost:5432/template1"
engine = create_engine(db_url)
connection = engine.connect()
# running this query in transaction throws an error
result = connection.execute("CREATE DATABASE temp_db")
会抛出错误:
ERROR: CREATE DATABASE cannot run inside a transaction block
现在,添加COMMIT
将结束一个由 sqlalchemy 启动的事务:
from sqlalchemy import create_engine
# replace url with your MySQL instance
db_url = "postgresql://postgres:secure_pass@localhost:5432/template1"
engine = create_engine(db_url)
connection = engine.connect()
# commiting will end a transaction
connection.execute("COMMIT")
# now this query runs fine
result = connection.execute("CREATE DATABASE temp_db")
并且不会引发任何错误。
推荐阅读
- biztalk - IDOC 不是从 SAP 触发但能够在 BizTalk 中看到
- python - Python Django Errno 54 '连接由对等方重置'
- zip - 如何在 Azure 数据工厂 v2 中解压缩 zip 文件
- javascript - 如何放大与轴文本保持一致的区域?谷歌图表
- android - 如何停止 ImageView 上的每个动画
- excel - 如何在excel VBA中计算一整行数字(暗淡为字符串)?
- javascript - 在 onChange 事件之后有条件地渲染子组件
- java - 使用返回数组的 Spring RestTemplate 发送获取请求
- pandas - 基于 OR AND 的 Pandas 过滤
- php - 未定义的属性:stdClass::$user AND 调用字符串上的成员函数 diffForHumans()