在 NestJS 中同步对数据库的多个请求
Synchronize multiple requests to database in NestJS
在我们的 NestJS 应用程序中,我们使用 TypeORM 作为 ORM 来处理数据库 tables 和 typeorm-transactional-cls-hooked
库。
现在我们在同步读取和修改数据库的请求时遇到问题。
样本:
@Transactional()
async doMagicAndIncreaseCount (id) {
const await { currentCount } = this.fooRepository.findOne(id)
// do some stuff where I receive new count which I need add to current, for instance 10
const newCount = currentCount + 10
this.fooRepository.update(id, { currentCount: newCount })
}
当我们从前端同时多次执行这个操作时,最后的计数是错误的。第一个事务读取currentCount
然后开始计算,在计算期间开始第二个事务也读取currentCount
,第一个事务完成计算并保存新的currentCount
,然后第二个事务完成并重写第一笔交易的结果。
我们的目标是在foo
table上一次只执行一次这个操作,其他请求应该等到
我试过像这样设置 SERIALIZABLE 隔离级别:
@Transactional({ isolationLevel: IsolationLevel.SERIALIZABLE })
确保一次只执行一个请求,但其他请求因错误而失败。你能给我一些解决办法的建议吗?
我从来没有使用过 TypeORM 而且你隐藏了你正在使用的数据库引擎。
无论如何要实现这个目标你需要写锁.
doMagicAndIncreaseCount
伪代码应该类似于
BEGIN TRANSACTION
ACQUIRE WRITE LOCK ON id
READ id RECORD
do computation
SAVE RECORD
CLOSE TRANSACTION
或者,您必须使用一些在数据库引擎上本机原子的操作;前任。 Redis 上的 INCR
操作。
编辑:
阅读 TypeORM find 文档,我可以提出如下建议:
this.fooRepository.findOne({
where: { id },
lock: { mode: "pessimistic_write", version: 1 },
})
P.S。查看问题的标签,我猜使用的数据库引擎是 PostgreSQL。
在我们的 NestJS 应用程序中,我们使用 TypeORM 作为 ORM 来处理数据库 tables 和 typeorm-transactional-cls-hooked
库。
现在我们在同步读取和修改数据库的请求时遇到问题。
样本:
@Transactional()
async doMagicAndIncreaseCount (id) {
const await { currentCount } = this.fooRepository.findOne(id)
// do some stuff where I receive new count which I need add to current, for instance 10
const newCount = currentCount + 10
this.fooRepository.update(id, { currentCount: newCount })
}
当我们从前端同时多次执行这个操作时,最后的计数是错误的。第一个事务读取currentCount
然后开始计算,在计算期间开始第二个事务也读取currentCount
,第一个事务完成计算并保存新的currentCount
,然后第二个事务完成并重写第一笔交易的结果。
我们的目标是在foo
table上一次只执行一次这个操作,其他请求应该等到
我试过像这样设置 SERIALIZABLE 隔离级别:
@Transactional({ isolationLevel: IsolationLevel.SERIALIZABLE })
确保一次只执行一个请求,但其他请求因错误而失败。你能给我一些解决办法的建议吗?
我从来没有使用过 TypeORM 而且你隐藏了你正在使用的数据库引擎。
无论如何要实现这个目标你需要写锁.
doMagicAndIncreaseCount
伪代码应该类似于
BEGIN TRANSACTION
ACQUIRE WRITE LOCK ON id
READ id RECORD
do computation
SAVE RECORD
CLOSE TRANSACTION
或者,您必须使用一些在数据库引擎上本机原子的操作;前任。 Redis 上的 INCR
操作。
编辑:
阅读 TypeORM find 文档,我可以提出如下建议:
this.fooRepository.findOne({
where: { id },
lock: { mode: "pessimistic_write", version: 1 },
})
P.S。查看问题的标签,我猜使用的数据库引擎是 PostgreSQL。