MySQL中事务执行时如果获取不到所需的行锁或表锁,就会进入锁等待状态,若等待时间超出设定阈值,数据库会自动中断当前等待的操作并返回错误,这是避免资源长时间阻塞的重要机制。锁等待超时的相关配置既可以在全局层面设置,也可以针对单个会话单独调整,满足不同业务场景的需求。

MySQL锁等待超时的核心参数
MySQL中和锁等待超时最相关的参数是innodb_lock_wait_timeout,这个参数用来设置InnoDB引擎中事务等待行锁的最长时长,默认值是50秒,单位是秒。当等待时间超过这个设定值时,MySQL会抛出ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction错误,回滚当前事务中等待锁的操作。
这个参数有两个作用范围,分别是全局级别和会话级别:
- 全局级别:修改后对所有新建立的会话生效,已经存在的会话不受影响
- 会话级别:仅对当前会话生效,不影响其他会话和全局配置
设置会话级别的超时中断时间
如果某个业务场景需要单独调整锁等待超时时间,不需要修改全局配置,直接设置当前会话的innodb_lock_wait_timeout即可,操作方式如下:
查看当前会话的超时配置
可以先查看当前会话的锁等待超时时间,确认当前配置:
-- 查看当前会话的innodb_lock_wait_timeout值 SHOW SESSION VARIABLES LIKE 'innodb_lock_wait_timeout';
修改当前会话的超时时间
使用SET SESSION命令可以临时修改当前会话的超时时间,修改后仅对当前连接有效,连接断开后配置会恢复为全局默认值:
-- 设置当前会话的锁等待超时时间为10秒,超过10秒自动中断等待 SET SESSION innodb_lock_wait_timeout = 10;
如果需要让配置永久生效,也可以将配置写入MySQL的配置文件my.cnf中,不过这是全局级别的配置,会影响所有会话:
[mysqld] -- 全局设置锁等待超时时间为30秒 innodb_lock_wait_timeout=30
自动处理锁等待超时的方案
除了设置超时时间让MySQL自动中断等待之外,还可以结合业务层的逻辑实现更完善的自动处理机制:
业务层捕获超时错误重试
当数据库返回锁等待超时的错误时,业务层可以捕获该错误,执行重试逻辑,避免直接返回失败给用户:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class MysqlLockWaitHandler {
private static final String URL = "jdbc:mysql://127.0.0.1:3306/test_db?useUnicode=true&characterEncoding=utf8";
private static final String USER = "root";
private static final String PASSWORD = "123456";
// 最大重试次数
private static final int MAX_RETRY = 3;
public void executeWithRetry() {
int retryCount = 0;
while (retryCount < MAX_RETRY) {
try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
Statement stmt = conn.createStatement()) {
// 设置当前会话的锁等待超时时间为10秒
stmt.execute("SET SESSION innodb_lock_wait_timeout = 10");
// 执行需要加锁的业务SQL
stmt.executeUpdate("UPDATE user SET balance = balance - 100 WHERE id = 1");
System.out.println("操作执行成功");
return;
} catch (SQLException e) {
// 捕获锁等待超时错误,错误码为1205
if (e.getErrorCode() == 1205) {
retryCount++;
System.out.println("锁等待超时,第" + retryCount + "次重试");
try {
// 重试前等待一段时间,避免频繁重试加重数据库压力
Thread.sleep(1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
} else {
// 其他错误直接抛出
e.printStackTrace();
return;
}
}
}
System.out.println("重试次数耗尽,操作失败");
}
}
监控锁等待状态主动处理
可以通过查询MySQL的 performance_schema 库的锁等待相关表,监控当前实例的锁等待情况,当发现某个事务等待时间过长时,主动kill掉对应的阻塞事务:
-- 查询当前正在等待锁的事务信息
SELECT
r.trx_id AS waiting_trx_id,
r.trx_mysql_thread_id AS waiting_thread,
r.trx_query AS waiting_query,
b.trx_id AS blocking_trx_id,
b.trx_mysql_thread_id AS blocking_thread,
b.trx_query AS blocking_query
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r ON r.trx_id = w.requesting_trx_id;
如果确认阻塞事务是异常事务,可以使用KILL命令终止对应的连接:
-- 终止线程ID为123的阻塞连接,123是上面查询结果中的blocking_thread值 KILL 123;
注意事项
- 会话级别的
innodb_lock_wait_timeout配置仅对当前会话有效,连接断开后配置会失效,如果需要长期生效需要每次建立连接后重新设置 - 超时时间设置过短可能会导致正常的事务因为短暂的锁竞争就失败,需要根据业务实际锁竞争情况合理设置
- 锁等待超时的错误回滚的是当前等待锁的语句,不是整个事务,如果需要回滚整个事务需要在业务层捕获错误后手动执行回滚操作
mysql锁等待超时设置innodb_lock_wait_timeout会话级别配置修改时间:2026-06-26 09:42:32