with engine.begin()和 with engine.connect()使用心得

以下内容完全是一个数据库小白的经验之谈,可能不太准确,见谅!

最近两天试图在树莓派上部署一个web应用,具体目标就是将接收到的数据转存到数据库中,一个是本地的kudu数据库,另一个是mysql数据库

# 如kudu库
impala.create_update_data('main', kudu_engine, df_main, 'main')
impala.create_update_data('child', kudu_engine, df_child, 'child')
impala.create_update_data('info', kudu_engine, df_info, 'info')
# 如mysql库
mysql.create_update_data('main', mysql_engine, df_main, 'main')
mysql.create_update_data('child', mysql_engine, df_child, 'child')
mysql.create_update_data('info', mysql_engine, df_info, 'info')
# impala
with engine.begin() as conn:
	conn.execute("UPSERT INTO {} ({}) VALUES ({})".format(table, keys, values))
# mysql
with engine.begin() as conn:
    conn.execute("REPLACE INTO {} ({}) VALUES ({})".format(table, keys, values))

但发现一个令人抓狂的问题:在本地x86机器上完全没问题,相同代码在树莓派上就完全看运气了(某些请求能正常入库,而大部分无法入库,而且没有任何异常)

最开始怀疑是因为机器性能导致,但尝试把导入kudu库的功能去掉后,发现入mysql库没有问题,所以是导入kudu库的代码问题。

将impala的‘with engine.begin() as conn:’换成:

conn = engine.connect()
conn.execute("UPSERT INTO {} ({}) VALUES ({})".format(table, keys, values))
conn.close()

发现一切又恢复正常了

看来是‘with engine.begin() as conn:’这条语句导致的

查了一下,上面这条语句好像是为了使用事物,但什么是事物,还需要进一步学习,最终把所有的‘with engine.begin() as conn:’改成‘with engine.connect() as conn:’,正常了!

总而言之,这里总结出的经验就是别用with engine.begin() as conn

参考:https://docs.sqlalchemy.org/en/13/core/connections.html


2020-04-30更新

在进行上面的修改后,又发现问题:树莓派中使用impala engine的df.to_sql(table, engine, if_exists=‘append’)会出问题,而mysql engine的貌似没有问题,所以索性把所有df.to_sql全部进行替换

dic = df.to_dict('records')
keys = ', '.join(
    key for key, value in dic[0].items()
)
values = ''
for item in dic:
    value = '(' + ', '.join(
    "'{}'".format(value) \
    if type(value) == str else "{}".format(value) \
    for key, value in item.items()
    ) + ')'
    values = (values + ',' + value).strip(',')
with engine.connect() as conn:
    conn.execute("INSERT INTO {} ({}) VALUES ({})".format(table, keys, values))
2025-03-16 12:38:46,235 INFO sqlalchemy.engine.Engine SELECT DATABASE() 2025-03-16 12:38:46,236 INFO sqlalchemy.engine.Engine [raw sql] () 2025-03-16 12:38:46,237 INFO sqlalchemy.engine.Engine SELECT @@sql_mode 2025-03-16 12:38:46,237 INFO sqlalchemy.engine.Engine [raw sql] () 2025-03-16 12:38:46,238 INFO sqlalchemy.engine.Engine SELECT @@lower_case_table_names 2025-03-16 12:38:46,238 INFO sqlalchemy.engine.Engine [raw sql] () 2025-03-16 12:38:46,239 INFO sqlalchemy.engine.Engine BEGIN (implicit) 2025-03-16 12:38:46,239 INFO sqlalchemy.engine.Engine DESCRIBE `testormsqlalchemy`.`student` 2025-03-16 12:38:46,239 INFO sqlalchemy.engine.Engine [raw sql] () 2025-03-16 12:38:46,240 INFO sqlalchemy.engine.Engine DESCRIBE `testormsqlalchemy`.`computer` 2025-03-16 12:38:46,241 INFO sqlalchemy.engine.Engine [raw sql] () 2025-03-16 12:38:46,242 INFO sqlalchemy.engine.Engine COMMIT 2025-03-16 12:38:46,246 INFO sqlalchemy.engine.Engine BEGIN (implicit) 2025-03-16 12:38:46,248 INFO sqlalchemy.engine.Engine INSERT INTO computer (name) VALUES (%s) 2025-03-16 12:38:46,249 INFO sqlalchemy.engine.Engine [generated in 0.00067s] ('华硕 ',) 2025-03-16 12:38:46,250 INFO sqlalchemy.engine.Engine INSERT INTO computer (name) VALUES (%s) 2025-03-16 12:38:46,251 INFO sqlalchemy.engine.Engine [cached since 0.002766s ago] ('戴尔',) 2025-03-16 12:38:46,251 INFO sqlalchemy.engine.Engine INSERT INTO computer (name) VALUES (%s) 2025-03-16 12:38:46,252 INFO sqlalchemy.engine.Engine [cached since 0.003822s ago] ('华为',) 2025-03-16 12:38:46,253 INFO sqlalchemy.engine.Engine INSERT INTO student (name, computer_id) VALUES (%s, %s) 2025-03-16 12:38:46,253 INFO sqlalchemy.engine.Engine [generated in 0.00042s] ('张三 ', 1) 2025-03-16 12:38:46,254 INFO sqlalchemy.engine.Engine ROLLBACK Traceback (most recent call last): File "D:\Python\lib\site-packages\sqlalchemy\engine\base.py", line 1964, in _exec_single_context self.dialect.do_execute( File "D:\Python\lib\site-packages\sqlalchemy\engine\default.py", li
03-17
<think> 我们正在使用Django ORM,但用户询问的是如何在Django ORM中使用`sqlalchemy.create_engine`。实际上,Django ORMSQLAlchemy是两个不同的ORM框架,通常不会在Django项目中使用SQLAlchemy的`create_engine`,因为Django有自己的数据库连接管理。 但是,如果确实有需要在Django项目中使用SQLAlchemy(例如,需要使用SQLAlchemy的某些高级特性),可以按照以下步骤操作: 1. **安装SQLAlchemy**: ```bash pip install sqlalchemy ``` 2. **在Django中使用SQLAlchemyEngine**: 在Django项目的任何地方(比如视图、管理命令等),可以创建一个SQLAlchemy引擎来连接数据库。注意,这个数据库连接是独立于Django ORM的,需要自行管理连接会话。 假设我们已经在Django的settings.py中配置了数据库,我们可以这样获取数据库连接字符串,然后创建SQLAlchemy引擎: ```python from sqlalchemy import create_engine from django.conf import settings # 从Django的配置中获取数据库连接信息 db_settings = settings.DATABASES['default'] user = db_settings['USER'] password = db_settings['PASSWORD'] database = db_settings['NAME'] host = db_settings['HOST'] or 'localhost' port = db_settings['PORT'] or '3306' # 默认MySQL端口 # 构建连接字符串,这里以MySQL为例 # 格式:dialect+driver://username:password@host:port/database db_url = f"mysql+mysqldb://{user}:{password}@{host}:{port}/{database}" # 创建引擎 engine = create_engine(db_url) ``` 3. **使用引擎执行SQL或操作SQLAlchemy ORM**: 有了引擎之后,你可以使用SQLAlchemy的核心连接或者ORM会话。例如,执行原生SQL: ```python with engine.connect() as connection: result = connection.execute("SELECT * FROM some_table") for row in result: print(row) ``` 或者使用SQLAlchemy的ORM(需要定义模型类): ```python from sqlalchemy.orm import sessionmaker Session = sessionmaker(bind=engine) session = Session() # 假设有一个SQLAlchemy定义的模型类 User # users = session.query(User).all() ``` 4. **注意事项**: - **独立连接池**:SQLAlchemy引擎会创建自己的连接池,因此会与Django ORM的连接池独立存在,这可能会导致数据库连接数增加。 - **事务管理**:需要手动管理事务,避免Django的事务冲突。 - **性能**:在Django中混用两个ORM可能会影响性能,并增加代码复杂度。 - **模型定义**:如果使用SQLAlchemy的ORM,需要另外定义模型,这与Django的模型是分离的。 通常情况下,除非有特殊需求(如使用SQLAlchemy的特定功能),否则建议在Django项目中坚持使用Django ORM。 §§相关问题§§ 1. 在Django项目中同时使用Django ORMSQLAlchemy有哪些潜在问题? 2. 如何避免SQLAlchemyDjango ORM同时使用时的数据库连接冲突? 3. 如何将Django ORM的模型转换成SQLAlchemy的模型? 4. 在Django中,什么情况下应该考虑使用SQLAlchemy而不是原生ORM? </think> 在Django项目中,直接使用SQLAlchemy的`create_engine`与Django ORM混合使用并不常见,因为两个库有各自独立的数据库连接管理会话机制。但若需在Django环境中使用SQLAlchemy进行特定操作,可按以下方式实现: ### 使用步骤 1. **安装依赖** ```bash pip install sqlalchemy django ``` 2. **在Django视图中创建SQLAlchemy引擎**(示例) ```python # views.py from sqlalchemy import create_engine, text from django.conf import settings from django.http import JsonResponse def sqlalchemy_query(request): # 从Django配置获取数据库信息 db_config = settings.DATABASES['default'] db_url = f"mysql+pymysql://{db_config['USER']}:{db_config['PASSWORD']}@{db_config['HOST']}:{db_config['PORT']}/{db_config['NAME']}" # 创建SQLAlchemy引擎 engine = create_engine(db_url) # 执行原生SQL查询 with engine.connect() as connection: result = connection.execute(text("SELECT * FROM your_app_yourmodel")) data = [dict(row) for row in result] return JsonResponse(data, safe=False) ``` 3. **路由配置** ```python # urls.py from .views import sqlalchemy_query urlpatterns = [ path('custom-query/', sqlalchemy_query), ] ``` ### 关键注意事项 1. **连接冲突风险** - Django ORM使用持久连接池 - SQLAlchemy引擎默认创建新连接 - 解决方案:共享连接池(需额外配置) 2. **事务管理** ```python # 显式事务控制示例 with engine.begin() as trans: trans.execute(text("UPDATE ...")) # 错误时自动回滚 ``` 3. **性能优化** - 复用引擎实例(避免重复创建) - 使用`scoped_session`管理线程安全会话 4. **模型映射** 若需操作Django模型表,需额外定义SQLAlchemy模型: ```python from sqlalchemy import Table, MetaData metadata = MetaData() django_table = Table( 'your_django_table', metadata, autoload_with=engine ) ``` ### 典型应用场景 1. 复杂报表生成(需高级SQL功能) 2. 批量数据操作(性能敏感场景) 3.数据库查询(混合不同数据库源) 4. 使用SQLAlchemy特有功能(如地理空间扩展) > **推荐做法**:优先使用Django ORM,仅在ORM无法满足需求时局部使用SQLAlchemy,并严格隔离数据库操作。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值