错误信息:SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
接口响应时间超长,报警日志中出现Lock wait timeout exceeded; try restarting transaction的错误
原因
mysql数据库采用InnoDB模式,一旦数据库锁超过innodb_lock_wait_timeout参数设置的锁等待的时间(默认50s)就会报错。
一个事务在等待另一个事务释放锁,另一个事务持有了一个资源的资源,导致另这个事务一直等待并超时。并且通过
trx_started
可发现,持有锁的事务是之前开启的,一直没释放。解决:
- 查看事务:
select * from information_schema.INNODB_TRX;
kill
掉 线程 后正常 kill 47491; (trx_mysql_thread_id)-- 查看事务 当前运行的所有事务 select * from information_schema.INNODB_TRX; --查看锁 当前出现的锁 select * from information_schema.INNODB_LOCKS; --查看锁等待 锁等待的对应关系 select * from information_schema.INNODB_LOCK_WAITS; # 当前线程详情 show full processlist;
查询全局等待事务锁超时时间
# 查询全局等待事务锁超时时间
SHOW GLOBAL VARIABLES LIKE 'innodb_lock_wait_timeout'
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50 |
+--------------------------+-------+
修改事务锁超时时间
set innodb_lock_wait_timeout=100;
set global innodb_lock_wait_timeout=100;
或者修改配置文件
# my.ini文件:
innodb_lock_wait_timeout = 100
其他方法:
-- 排查事务的SQL
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE trx_query LIKE '%表名%';
KILL 掉执行的线程
## 查看当前被使用的表
show OPEN TABLES where In_use > 0;
-- SHOW OPEN TABLES:列举在表缓存中当前被打开的非TEMPORARY表。
-- In_use:表当前被查询使用的次数。如果该数为零,则表是打开的,但是当前没有被使用
SELECT
trx_id AS `事务ID`,
trx_state AS `事务状态`,
trx_requested_lock_id AS `事务需要等待的资源`,
trx_wait_started AS `事务开始等待时间`,
trx_tables_in_use AS `事务使用表`,
trx_tables_locked AS `事务拥有锁`,
trx_rows_locked AS `事务锁定行`,
trx_rows_modified AS `事务更改行`
FROM
information_schema.innodb_trx ;
SELECT
lock_id AS `锁ID`,
lock_trx_id AS `拥有锁的事务ID`,
lock_mode AS `锁模式 `,
lock_type AS `锁类型`,
lock_table AS `被锁的表`,
lock_index AS `被锁的索引`,
lock_space AS `被锁的表空间号`,
lock_page AS `被锁的页号`,
lock_rec AS `被锁的记录号`,
lock_data AS `被锁的数据`
FROM
information_schema.innodb_locks;
SELECT
requesting_trx_id AS `请求锁的事务ID`,
requested_lock_id AS `请求锁的锁ID`,
blocking_trx_id AS `当前拥有锁的事务ID`,
blocking_lock_id AS `当前拥有锁的锁ID`
FROM
innodb_lock_waits