首页 > 解决方案 > 锁定行以进行读取和更新 - 一次只有一个进程应该更新一行

问题描述

我被要求检查我需要帮助的生产问题。我试图了解 SQL Server 中可用的隔离级别和不同的锁。


我有一个JOB_STATUS有列的表job_name (string, primary key), job_status (string), is_job_locked (string)

样本数据如下:

工作名称 工作现状 is_job_locked
作业_A 不活跃 ñ
工作_B 跑步 ñ
工作_C 成功 ñ
作业_D 跑步 ñ
工作_E 不活跃 ñ

多个进程可以通过调用存储过程并传递job_nameas 输入参数来同时更新表。如果两个不同的行同时被不同的进程更新,那很好。

但是,两个进程不应同时更新同一行。

更新查询示例如下:

update JOB_STATUS set is_job_locked='Y' where job_name='JOB_A' and is_job_locked='N';

在这里,如果两个进程正在更新同一行,那么一个进程应该等待另一个进程完成。此外,如果is_job_locked列值被一个进程更改为Y,则另一个进程不应再次更新它(如果锁定正确,我的更新语句应该处理)。

那么我该如何进行这种行级锁定并确保更新查询在使用存储过程进行更新之前从行中读取最新数据。

另外,想根据条件获取更新查询是否更新了行或没有更新的返回值,以便我可以在进一步的应用程序流程中使用该值。

标签: sql-serverazure-sql-database

解决方案


RE:“如果两个进程正在更新同一行,那么一个进程应该等待另一个进程完成。”

这就是锁定在 SQL Server 中的工作方式。UPDATE 在行上采用排他锁——其中“排他”表示该词的英文含义:UPDATE 进程在运行时已排除(锁定)所有其他进程。其他进程现在等待 UPDATE 完成。这包括事务隔离级别 READ COMMITTED 及以上的 READ 进程。当 UPDATE 锁被释放时,下一条语句就可以访问该值。

如果您正在寻找的是 2 个进程不能同时更改单个表中的同一行,那么 SQL Server 会立即为您执行此操作,您无需添加自己的“is_job_locked”列。

但是,通常使用 is_job_locked 列来控制对单个表之外的访问。例如,它可用于防止第二个进程启动已在运行的作业。进程 A 将标记 is_job_locked,然后启动作业。进程 B 将在尝试开始作业之前检查标志。


推荐阅读