为什么mysql insert会导致锁等待超时异常

zhu*_*wei 3 mysql transactions mybatis

当执行单元测试( mvn test)时有时会出现以下异常

org.springframework.dao.CannotAcquireLockException:

### Error updating database.  Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
### The error may involve com.foo.dao.mapper.TestMapper.insertSuccesfulPaymentOrder-Inline
### The error occurred while setting parameters
### SQL: insert into order(order_seq,note,user_id,product_id, pay_status) values(uuid(),'',?,?,1)
### Cause: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
; SQL []; Lock wait timeout exceeded; try restarting transaction; nested exception is java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction
Run Code Online (Sandbox Code Playgroud)

mysql 文档我知道

InnoDB 事务在放弃之前等待行锁的时间长度(以秒为单位)。默认值为 50 秒。尝试访问被另一个 InnoDB 事务锁定的行的事务最多等待这么多秒才能对该行进行写访问,然后才会发出以下错误:

ERROR 1205 (HY000):超出锁定等待超时;尝试重新启动事务

所以我认为只有在更新某些行时才会出现此异常,但我的是insert操作,为什么仍然有此异常?我怎样才能直接在 mysql 会话中重现它?

Ric*_*ews 6

无论 ORM 使用 get_lock() ,默认值 50 秒都意味着存在另一个长时间运行的查询,由于各种原因,这可能是不受欢迎的。如果您在开发数据库实例上的单元测试中遇到超过锁定等待超时的情况,则尤其如此。

因此,您必须使问题可重现,并确定哪个查询(不是插入)是有罪的并且具有锁。

增加默认超时以在 mysql cli 上提供足够的交互时间。运行测试并在获得锁等待超时的测试上进行中断。

SELECT * FROM `information_schema`.`innodb_locks`;
Run Code Online (Sandbox Code Playgroud)

将显示当前的锁。

select * from information_schema.innodb_trx where trx_id = [lock_trx_id];
Run Code Online (Sandbox Code Playgroud)

将显示涉及的交易

SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST where id = [trx_mysql_thread_id];
Run Code Online (Sandbox Code Playgroud)

将显示所涉及的连接,并可能显示其锁定导致锁定等待超时的查询。也许有未提交的交易。