Jos*_*eph 5 postgresql node.js typescript typeorm nestjs
我想使用 Nestjs 和 TypeORM 在 PostgreSQL 中实现数据库行锁定。请任何人告诉我如何以正确的方式实施它。我尝试使用以下代码,但不确定它是否锁定特定行。
async testFun(): Promise<any> {
const user = await this.userRepo
.createQueryBuilder("user")
.useTransaction(true)
.setLock("pessimistic_write")
.where("id = :id", { id: 2 })
.getOne()
const updateResult: any = await this.userRepo.createQueryBuilder('test')
.update()
.set({ fullname: "frm3000" })
.where("id = :id", { id: 2 })
.execute();
return updateResult;
}
Run Code Online (Sandbox Code Playgroud)
TypeORM 生成的查询是,
query: START TRANSACTION
query: SELECT * FROM "users" "user" WHERE id = $1 FOR UPDATE -- PARAMETERS: [2]
query: COMMIT
query: UPDATE "users" SET "fullname" = $1 WHERE "id" = $2 -- PARAMETERS: ["from3000",2]
Run Code Online (Sandbox Code Playgroud)
这里提交是在更新查询之前完成的,因此怀疑该行是否被锁定。
另外,我想在本地主机上测试它,使用两个不同的端口 localhost:3000 和 localhost:3001。因此,我在另一个具有延迟端口 3001 的应用程序中添加了相同的控制器和服务代码,
async testFun(): Promise<any> {
const user = await this.userRepo
.createQueryBuilder("user")
.useTransaction(true)
.setLock("pessimistic_write")
.where("id = :id", { id: 2 })
.getOne()
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
await sleep(20000);
const updateResult: any = await this.userRepo.createQueryBuilder('test')
.update()
.set({ fullname: "frm3001" })
.where("id = :id", { id: 2 })
.execute();
return updateResult;
}
Run Code Online (Sandbox Code Playgroud)
请让我知道这种方法是否正确或建议更好的方法(如果有)。而且测试方法也不起作用。
谢谢!
由于您正在运行query
而没有启动transaction
on TypeORM
. 所有的个体queries
都被视为一个单独的transaction
个体database
。
queries
要在 a 中运行一组,single transaction
您必须Demarcate transaction
在应用程序级别运行。transaction
设置分界的方法之一TypeORM
是使用QueryRunner。
执行以下步骤:
const queryRunner = getConnection().createQueryRunner();
try {
await queryRunner.connect();
await queryRunner.startTransaction();
const user = await queryRunner.manager.getRepository(User)
.createQueryBuilder("user")
.useTransaction(true)
.setLock("pessimistic_write")
.where("id = :id", { id: 2 })
.getOne()
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
await sleep(20000);
const updateResult: any = await queryRunner.manager.getRepository(User)
.createQueryBuilder('test')
.update()
.set({ fullname: "frm3001" })
.where("id = :id", { id: 2 })
.execute();
await queryRunner.commitTransaction();
return updateResult;
} catch(e) {
await queryRunner.rollbackTransaction();
} finally {
await queryRunner.release();
}
Run Code Online (Sandbox Code Playgroud)
注意:永远不要忘记释放queryRunner,否则你的数据库连接将被用完。
希望这可以帮助。