Mysql更新数据库操作时产生的死锁问题(Deadlock found…)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to…
产生问题代码
MybatisPlus的写法,.eq类似于Where后的语句。
@Overridepublic void updateProgrammeUser(Long userId, String externalNameKey, Long programmeId,String externalProgrammeKey, String externalKey, String status) {
UpdateWrapper<ExternalProgrammeUserModel> updateWrapper = new UpdateWrapper<>();updateWrapper.lambda().set(ExternalProgrammeUserModel::getStatus, Constant.External.SUCCESS).set(ExternalProgrammeUserModel::getExternalProgrammePrimaryKey, externalProgrammeKey).set(ExternalProgrammeUserModel::getExternalUserPrimaryKey, externalNameKey).eq(ExternalProgrammeUserModel::getExternalKey, externalKey).eq(ExternalProgrammeUserModel::getInternalUserId, userId).eq(ExternalProgrammeUserModel::getInternalProgbaseMapper.update(null, updateWrapper);}
场景描述:
5个类以异步的方式调用此方法,更新同一张表。
可能产生的原因
- where后面的字段没有加索引
- (以上面代码举例)想当然的为where后的每一个字段加上索引,此时认为后面三个字段可以确定同一行,认为只锁住了一行。
其实行锁是对索引加锁,那么当where语句中包含多个条件时候,mysql在执行时也只用到了区分度最大的字段,所以实际上只使用了一个字段的索引,那么根据这个字段进行过滤出来的记录数可能就不止一条,也就是锁住了本不该锁住的行。
解决方案
使用联合索引(以上面代码举例),在数据库添加external_key
,internal_user_id
,internal_programme_id
三个字段的联合索引。
alter table muses_external_programme_user add index update_test_index(external_key,internal_user_id,internal_programme_id);