mysqlconnector 本身不会无缘无故地锁表
时间: 2026-04-18 19:03:52
(部分内容来自网络,其真实性存疑,为了避免对您造成误导,请谨慎甄别。)
别急,这个问题我也遇到过,真的很烦人。mysqlconnector 本身不会无缘无故地锁表,问题通常出在使用方式上。我帮你总结了几个最常见的原因和解决办法:
🚨 最常见原因:没关闭的 Session 或连接
这是80%情况下的罪魁祸首。
当你使用 session.query() 查询后,如果不关闭 session,它会一直 holding 着一个数据库事务。MySQL 的 InnoDB 引擎为了保持数据一致性,会在这个事务期间对涉及的表持有元数据锁(Metadata Lock)。
错误的代码模式:
# ❌ 这样会锁表! result = session.query(User).all() # ... 做一些其他操作(包括 pandas 处理) # 然后直接 drop_all() 或执行 DDL 操作 Base.metadata.drop_all(bind=engine) # 这里会卡住!
正确的做法:
# ✅ 用完立刻关闭 result = session.query(User).all() session.close() # 或者 session.commit() / session.rollback() # 然后再执行 DDL 操作
🔍 排查步骤
1. 看看是谁锁了表
在 MySQL 里执行这个命令,看看当前的连接状态:
SHOW PROCESSLIST;
如果看到一堆 Sleep 状态的连接,就是它们在捣乱。
2. 检查你的代码结构
# 确保你的 Session 使用正确 from sqlalchemy.orm import Session
# 推荐使用 with 语句,自动管理事务 with Session(engine) as session: result = session.query(User).all() # 这里处理数据 # 出了 with 块,事务自动提交/回滚,连接自动关闭
🛠️ 解决方案
方案1:显式关闭 Session(最简单)
# 在你代码的适当位置加上 session.close() # 或者 session.commit() # 如果有未提交的更改
方案2:使用 NullPool 禁用连接池
如果连接池导致问题,可以禁用连接池:
from sqlalchemy.pool import NullPool
engine = create_engine( 'mysql+mysqlconnector://root:123456@localhost:3306/or', poolclass=NullPool # 每次用完就关连接,不复用 )
方案3:调整隔离级别
如果还是不行,可以试试调整隔离级别(但这是最后的选择):
engine = create_engine( 'mysql+mysqlconnector://root:123456@localhost:3306/or', isolation_level="READ COMMITTED" # 减少锁的范围 )
📌 记住这个铁律
SQLAlchemy 的事务和连接不是自动释放的! 在以下情况中,事务会保持开启:
- Session 创建后,执行了查询,但没有 commit()、rollback() 或 close()
- 连接池中的连接,虽然在 pool 里,但可能还持有之前事务的锁
经验法则:用完 Session 就像用完厕所要冲水一样——必须关闭或提交! 💩
试试加上 session.close(),这个问题大概率就解决了。如果还不行,把具体的代码贴出来,我帮你看看。