Prisma删除导航数据遇写入冲突/死锁问题及优化咨询
解决Prisma删除导航数据的写冲突问题及单条删除实现
一、单条命令删除指定用户的所有导航数据
你不需要分两次执行删除操作,所有属于目标用户的导航项(无论是否为父级)都可以通过单条deleteMany语句一次性删除,直接匹配userId即可:
await this.navigation.deleteMany({ where: { userId: userId } })
这种写法既简化了代码,也从根源上减少了多次删除操作引发的数据库锁竞争概率。
二、解决写冲突/死锁报错
如果使用单条命令后仍遇到类似报错,可以尝试以下几种方案:
- 用Prisma事务包裹操作:将删除逻辑放在事务中,保证操作的原子性,降低锁冲突的发生几率:
await this.prisma.$transaction(async (tx) => { await tx.navigation.deleteMany({ where: { userId: userId } }) }) - 调整关联的
onDelete策略:如果业务逻辑允许,修改Prisma模型中parent关联的删除策略为Cascade,这样删除父级导航时会自动删除其子级(需重新生成数据库迁移):
注意:修改后依然推荐使用parent Navigation? @relation(name: "Navigation_children", fields: [parentId], references: [id], onDelete: Cascade, onUpdate: NoAction)userId匹配的单条删除逻辑,这是最直接的方式。 - 添加重试机制:针对偶发的写冲突,在代码中增加重试逻辑,通过
try-catch包裹操作,失败后重试几次:const maxRetries = 3; let retries = 0; while (retries < maxRetries) { try { await this.navigation.deleteMany({ where: { userId: userId } }); break; } catch (error) { retries++; if (retries === maxRetries) throw error; await new Promise(resolve => setTimeout(resolve, 100)); } }
内容的提问来源于stack exchange,提问作者Luis Chan
相关产品推荐
相关产品推荐

