mysql事务和锁超时异常lock wailt timeout exceeded
程序员文章站
2024-01-14 09:20:28
...
当两个事务中,都会同一行记录进行操作的时候,可能会触发死锁,最终抛出超时异常
验证如下
首先在当前的数据库连接会话中
将数据库事务设置为手动提交
set @@autocommit=0;
SHOW VARIABLES like ‘%autocommit%’
然后在当前会话中
执行, 但先不commit
这个时候在该会话中,事务还没提交
此时在该会话中去查询
数据已经看不到了。
但是此时在另一个会话中 ,数据还在,因为之前那个会话的事务没有提交
如果在另一个会话中,也对这行记录进行操作
因为会话1的事务没有提交,且在会话1中对记录为aaa的行进行了加锁
此时会话2也去对记录为aaa的行进行删除,需要去等待会话1将锁释放。
但是等待时间在SHOW VARIABLES LIKE ‘innodb_lock_wait_timeout’; 可以看到 是50秒
超出这个时间就会抛出异常 lock wailt timeout exceeded
因此,最好不要在代码中有特别耗时的大事务,除了容易造成获取锁超时,也容易死锁。
比如说同时在会话1中(操作行1 , 操作行2) ,在会话2中(操作行2,操作行1),彼此等待对方释放X锁。
一些用于查看数据库状态的sql
-- 当前运行的所有事务
select * from information_schema.INNODB_TRX
-- 如果发现有超长时间的慢sql 用 kill trx_mysql_thread_id,然后在查询中kill掉就行
show engine innodb status
-- 显示是自动提交还是手动
show variables like 'autocommit'
-- 查看当前数据库进程
show PROCESSLIST
-- 查询当前会话等待事务锁超时时间 默认是50秒:
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
-- 查询innodb锁
SELECT * FROM information_schema.INNODB_LOCKs;
-- 查询在等待锁的sql
select * from information_schema.INNODB_LOCK_WAITS
推荐阅读