Lock wait timeout exceeded; try restarting transaction

Lock wait timeout exceeded; try restarting transaction 是 MySQL 中常见的并发错误,意味着当前事务在尝试获取行锁时,等待时间超过了系统设定的阈值(默认为 50 秒),从而被 MySQL 主动终止并回滚。

这通常‌是‌数据库磁盘满载锁竞争‌问题导致的。

以MySQL5.7为例

第一种情况------锁竞争

第一步:查找阻塞源(谁持有了锁?)

执行以下 SQL,找出正在等待锁的事务以及阻塞它的事务:

sql 复制代码
SELECT 
    r.trx_id AS waiting_trx_id,
    r.trx_mysql_thread_id AS waiting_thread_id,
    r.trx_query AS waiting_query,       -- 被阻塞的SQL
    b.trx_id AS blocking_trx_id,
    b.trx_mysql_thread_id AS blocking_thread_id,
    b.trx_query AS blocking_query       -- 持有锁的SQL (若为NULL,说明该事务当前空闲但未提交)
FROM information_schema.INNODB_TRX r
JOIN information_schema.INNODB_LOCK_WAITS w ON r.trx_id = w.requesting_trx_id
JOIN information_schema.INNODB_TRX b ON b.trx_id = w.blocking_trx_id;

**重点关注 blocking_query**‌:

  • 如果有具体 SQL,说明该 SQL 所在的事务持有了锁。
  • 如果为 NULL,说明该事务之前执行过 SQL,现在处于空闲状态(Sleep),但事务未提交,依然持有锁。

第二步:找到第一步中查出的 blocking_thread_id,执行 Kill 命令释放锁

sql 复制代码
KILL <blocking_thread_id>;

注意:不要 Kill 报错的那个线程(waiting_thread),因为它已经被 MySQL 终止了。必须 Kill 持有锁的线程。

至此Lock wait timeout exceeded; try restarting transaction 问题应该已经得到解决,后期记得优化该SQL,如果问题还没的到解决则可能是MySQL宿主机的云盘满了(自己在服务器安装的MySQL数据库)

第二种情况------磁盘满载

第一步:分析磁盘满载原因

由于数据库开启了主从复制,保留了binlog的二进制文件,同时主库还从三方库定时同步数据,这就导致不停地产生binlog二进制文件,500GB的数据盘一周就被binlog二进制文件占满了(阔怕)

第二步:找到binlog二进制文件

执行以下命令查看分区的总体使用情况:

bash 复制代码
df -h

定位到被占满的分区后,比如data区被占满了,执行以下命令逐层查看 /data 下各子目录的大小,定位占用空间最大的位置,最终定位到存放binlog二进制文件的目录:

bash 复制代码
du -sh /data/* | sort -rh

第三步:删除历史binlog二进制文件,建议保留最新的binlog二进制文件,其余的都删掉,如果配置了主从复制则最新的那个binlog二进制文件一定别删,否则还得重新配置主从复制

bash 复制代码
# 例如binlog二进制文件是mysql-bin.00001
rm -f /data/mysql/data/mysql-bin.00001

第四步:配置 Binlog 自动过期,编辑/etc/my.cnf,添加如下参数

bash 复制代码
[mysqld]
expire_logs_days = 7  # 根据业务需求调整保留天数

第五步:重启mysql

bash 复制代码
systemctl restart mysql

启动报错一,如下,说明把最新的mysql-bin.000464二进制文件删除了,MySQL 在启动时尝试读取二进制日志索引中记录的最新 binlog 文件,但该文件‌不存在:

bash 复制代码
2026-06-16T02:05:46.755343Z 0 [ERROR] Failed to open log (file './mysql-bin.000464', errno 2)
2026-06-16T02:05:46.755350Z 0 [ERROR] Could not open log file

解决办法有两个方案

方案一:修正 Binlog 索引文件(推荐)

bash 复制代码
vim /data/mysql/data/mysql-bin.index
# 删除缺失文件的行,保存退出
  • 删除索引文件中指向‌不存在文件‌的行。
  • mysql-bin.000464 确实被误删,且你不需要该日志之后的数据恢复,请删除索引中从 mysql-bin.000464 开始的所有行。
  • 注意‌:确保索引中保留的最后一个文件在磁盘上是真实存在的。
  • 重新启动 MySQL

方案二:重置 Binlog(若无需保留旧日志)

bash 复制代码
#清空binlog文件和删除索引文件
rm -f /data/mysql/data/mysql-bin.index
rm -f /data/mysql/data/mysql-bin.*
  • 清空binlog文件和删除索引文件
  • 重启MySQL,MySQL 启动时会自动创建新的 mysql-bin.000001 和索引文件。

启动报错二,如下:

bash 复制代码
ERROR! The server quit without updating PID file (/data/mysql/data/deploy-test-prd-x8601.pid).

解决方法,清理残留 PID 文件和err文件

bash 复制代码
rm -f /data/mysql/data/deploy-test-prd-x8601.pid
rm -f /data/mysql/data/deploy-test-prd-x8601.err
  • 重启MySQL