赞
踩
死锁发生了。Lock wait timeout exceeded; 超过锁定等待超时,也就是死锁了,两个线程同时争夺资源,没有先后顺序,这就造成了死锁。产生死锁的原因有很多,更容易在多线程、线程池、多条sql操作同一张表分开来写。有必要对这些容易产生死锁的接口用jemet性能测试。
文中告诉你,错误来自UPDATE mch_user SET is_admin=? WHERE id=?### 这条,当然sql语句没有错,id是主键索引,is_admin就一普通字段。
它说错误可能存在com.merchant.server.mapper.MchUserMapper.updateById这里,MchUserMapper只看到的是mybatis-plus BaseMapper的updateById
实际上我用的是IService里面的updateById,从而间接的使用到了BaseMapper的updateById
具体框架可以看到
default boolean updateById(T entity) {
return SqlHelper.retBool(this.getBaseMapper().updateById(entity));
}
查看mysql事务和锁的情况
show processlist;
select * from information_schema.innodb_trx;
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
发现两个事务都要锁住用户表的主键
同一个线程,涉及到了两个事务,sql获取的sqlsession和同一个线程的其他sql不一致,两个sqlsession对应不是一个事务
最后处理的结果是把两个update同一张表的逻辑层优化成批量操作用来解决死锁问题,大部分的改为批量可以避免多个事务造成的死锁问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。