Flask应用执行MySQL更新时触发Lock wait timeout exceeded错误求助
嘿,这个Lock wait timeout exceeded的问题确实挺闹心的,尤其是之前运行正常突然出状况的情况。我来帮你梳理下几个关键排查方向和解决办法:
1. 排查未提交的长事务占用锁
虽然你这段代码里没显式开启事务,但MySQL默认的autocommit可能被意外修改,或者其他地方的代码隐式开启了事务没提交。你可以用这几个SQL语句查看当前锁的占用情况:
-- 查看当前活跃的事务 SELECT trx_id, trx_started, trx_state, trx_query FROM INFORMATION_SCHEMA.INNODB_TRX; -- 查看当前持有的锁 SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; -- 查看锁等待关系 SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
如果发现有长时间运行的事务,尤其是涉及tbl表的,要么等它自动完成,要么手动终止(用KILL [trx_id];),同时要找到为什么这个事务没提交——比如是不是其他代码里开启了事务但忘了commit或rollback。
2. 检查filename字段的索引情况
你的UPDATE语句是通过filename作为筛选条件,如果这个字段没有建立索引,MySQL会做全表扫描,这时候会锁定表中大量行,很容易引发锁冲突。你可以先查看表的索引:
SHOW INDEX FROM tbl;
如果没有filename的索引,赶紧创建一个:
CREATE INDEX idx_tbl_filename ON tbl(filename);
这个优化能直接把锁的范围缩小到你要更新的那一行,大概率能解决大部分锁冲突问题。
3. 确认数据库连接的事务自动提交设置
有些Flask数据库扩展(比如Flask-SQLAlchemy)可能会修改autocommit的默认值,导致单条语句也变成未提交的事务。你可以在执行UPDATE后显式提交事务:
query = 'update tbl set x="bla" where filename=%s' cursor.execute(query, fileName) connection.commit() # 显式提交,确保锁被释放
如果用的是SQLAlchemy ORM,也要确保操作后调用了db.session.commit()。
4. 排查并发操作或批量任务
近期是不是业务量上涨了?或者新增了定时任务、批量脚本在操作同一张表?比如有没有其他进程在批量更新tbl,或者做全表查询、导出等操作?你可以查看当前MySQL的进程列表:
SHOW PROCESSLIST;
找到那些长时间运行的、和tbl相关的SQL,看看是不是它们在占用锁资源。
5. 临时调整锁等待超时时间(治标办法)
如果是业务场景确实需要更长的等待时间,可以临时调整MySQL的锁超时参数:
SET GLOBAL innodb_lock_wait_timeout = 120; -- 调整为120秒,根据实际情况修改
但这只是临时缓解,还是要找到锁冲突的根源才能彻底解决问题。
内容的提问来源于stack exchange,提问作者jonb

