数据库中有2行符合查询条件。如果我们运行两个并行查询,第一个查询会锁定两行并返回一行,而第二个查询将返回
null
。
最好能够仅锁定一行(返回的)以避免这种情况。
const queryRunner : QueryRunner = this.connect.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
const identificationProcess = await queryRunner.manager
.getRepository(IdentificationProcessEntity)
.createQueryBuilder("identification_process")
.orderBy("identification_process.updated_at", "ASC")
.where("identification_process.status = :status", { status: IdentificationStatusEnum.Scanning })
.useTransaction(true)
.setLock("pessimistic_write")
.setOnLocked("skip_locked")
.take(1)
.getOne()
我尝试过更改查询参数。
MariaDB - v10.8.4
SQL:
query: SELECT `identification_process`.`uid` AS `identification_process_uid`, `identification_process`.`user_uid` AS `identification
_process_user_uid`, `identification_process`.`status` AS `identification_process_status`, `identification_process`.`attempts` AS `id
entification_process_attempts`, `identification_process`.`expire_at` AS `identification_process_expire_at`, `identification_process`
.`created_at` AS `identification_process_created_at`, `identification_process`.`updated_at` AS `identification_process_updated_at`,
`identification_process`.`procedure_uid` AS `identification_process_procedure_uid` FROM `identification_process` `identification_pro
cess` WHERE `identification_process`.`status` = ? ORDER BY `identification_process`.`updated_at` ASC LIMIT 1 FOR UPDATE SKIP LOCKED
-- PARAMETERS: ["Scanning"]
锁始终位于索引上。因此,为了保证查询获得最少数量的锁,查询需要以最佳方式使用索引,以创建最少的锁。
虽然索引是一个又大又重要的主题,但强烈建议使用它来支持最佳查询(和节能),让我们看看问题中的查询。
有一个简单的单表查找,没有连接,因此请查看
where
标准。在 status
上搜索需要状态索引。找到后,结果按updated_at
排序。这构成了复合索引的第二部分。
因此 SQL 中的索引是通过以下方式创建的:
CREATE INDEX idx_status_updated_at ON identification_process (status, updated_at)
或者查看 TypeORM 文档:
@Entity()
...
@Index(["status", "updated_at"])
...
export class identification_process {