用完连接后没有关闭
时间: 2026-04-18 19:03:22
(部分内容来自网络,其真实性存疑,为了避免对您造成误导,请谨慎甄别。)
兄弟,别急,我懂你的崩溃。pd.read_sql 后表还被锁着,说明连接肯定没彻底关上。
用 engine 传参能避免一部分问题,但如果你之前操作出错,或者有没关干净的连接,残留的事务会一直占着茅坑不拉屎。
咱们换个思路,不猜了,直接进数据库“抓鬼”。按照下面的步骤,找到那个死赖着不走的连接,一把 KILL 掉,世界就清净了。
🚨 第一步:立刻找出是谁在捣乱
在你的 MySQL 客户端(Navicat、DBeaver 或命令行)里跑这段“查户口”的 SQL:
SELECT p.ID AS 连接ID, p.USER AS 用户, p.HOST AS 主机, p.TIME AS 空闲秒数, p.COMMAND AS 状态, p.INFO AS 正在执行的SQL FROM information_schema.PROCESSLIST p WHERE p.COMMAND != 'Sleep' -- 先找没在睡觉的 OR p.TIME > 60 -- 或者睡了超过60秒的(这些就是嫌疑人) ORDER BY p.TIME DESC;
* 重点关注:TIME 值很大(比如几百、几千)且 COMMAND 是 Sleep 的连接。这就是你之前没关掉的连接。
* 看 INFO 列:如果能直接看到你之前执行的那条 SELECT * FROM or_kryanshi,那 100% 就是它了!
🔪 第二步:物理消灭“僵尸”连接
一旦你锁定了捣乱的 连接ID(假设是 12345),执行下面的命令直接干掉它:
-- 把 12345 换成你查出来的那个数字 KILL 12345;
> 注意:这一步会立刻中断那个连接,但不会影响你现在的 Python 程序。执行完 KILL 后,你再试试去改表结构或做其他操作,应该会发现锁瞬间就解开了。
🩺 第三步:深度体检(如果还不行)
如果杀了那些“睡死”的连接还不管用,说明可能有更深层的“锁”在作祟。再用这套 SQL 查一下元数据锁:
-- 查看当前谁在锁着表(针对你的 or_kryanshi) SELECT OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_STATUS, OWNER_THREAD_ID FROM performance_schema.metadata_locks WHERE OBJECT_NAME = 'or_kryanshi';
-- 查看当前活跃的事务(这往往是元凶) SELECT * FROM information_schema.INNODB_TRX\G;
* 如果看到 LOCK_STATUS 为 PENDING:说明有一个操作正在排队等锁,你需要根据 OWNER_THREAD_ID 找到它并 KILL。
* 如果 INNODB_TRX 里查到了东西:trx_started 是很久以前的时间,记下 trx_mysql_thread_id,直接 KILL 掉它。
💡 总结:防身术(以后别再踩坑了)
找到原因了,是因为你最开始用 raw_connection() 并且忘了 close(),留下了“僵尸会话”。
以后记住这个标准写法,保证安全:
# ✅ 铁律:直接用 engine,让它自己管自己
df = pd.read_sql_query("SELECT * FROM or_kryanshi WHERE 1=1;", engine)
# ⚠️ 如果非要手动拿连接,用 with 语句,它跑完会自动关门
with engine.raw_connection() as conn:
df = pd.read_sql_query("SELECT * FROM or_kryanshi WHERE 1=1;", conn)
# 跑完这里,连接就自动关了,绝对不留后患快去数据库里执行第一步的查户口命令,找到那个 ID 杀了,问题立刻解决。