fix(auth): avoid gap locks when creating accounts

This commit is contained in:
2026-09-30 11:29:02 +08:00
parent c7945ad8fd
commit 6731be1a6b
2 changed files with 54 additions and 4 deletions
@@ -9,6 +9,7 @@ import jakarta.annotation.Resource;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.dao.DuplicateKeyException;
import com.baiyue.common.audit.BusinessAudit;
import java.util.Locale;
@@ -63,7 +64,9 @@ public class AccountManagementService {
String appCode = request.appCode() == null ? "MERCHANT"
: request.appCode().trim().toUpperCase(Locale.ROOT);
validateScope(appCode, request.tenantId());
AuthAccount existing = repository.findById(request.accountId());
// Locking a missing key takes an InnoDB gap lock and can deadlock
// unrelated account inserts. The unique indexes arbitrate creation.
AuthAccount existing = repository.findCurrentById(request.accountId());
if (existing != null) {
if (sameIdentity(existing, request, appCode)) return summary(existing);
throw new BizException(ResultCode.CONFLICT, "认证账号标识已被其他成员使用");
@@ -88,7 +91,13 @@ public class AccountManagementService {
account.setDefaultMembershipId(request.membershipId());
account.setDefaultAppCode(appCode);
account.setDeleted(0);
repository.insert(account);
try {
repository.insert(account);
} catch (DuplicateKeyException duplicate) {
AuthAccount winner = repository.findById(request.accountId());
if (winner != null && sameIdentity(winner, request, appCode)) return summary(winner);
throw new BizException(ResultCode.CONFLICT, "认证账号标识或登录账号已被使用");
}
return summary(account);
}