SQL Server锁定在Python中无法读取和更新的行
我需要在SQL Server和Python中锁定一行,读取并更新该行的一个字段,以使程序能够同时运行多个进程,从而避免争用情况 我正在使用以下代码,但在Python中它更新一个Id(即3411)并返回另一个Id(即3071)。如果我直接在SSMS中运行相同的SQL代码,它会更新并返回相同的IdSQL Server锁定在Python中无法读取和更新的行,python,sql-server,concurrency,locking,Python,Sql Server,Concurrency,Locking,我需要在SQL Server和Python中锁定一行,读取并更新该行的一个字段,以使程序能够同时运行多个进程,从而避免争用情况 我正在使用以下代码,但在Python中它更新一个Id(即3411)并返回另一个Id(即3071)。如果我直接在SSMS中运行相同的SQL代码,它会更新并返回相同的Id import pyodbc def read_and_update_files_queue(self): conn = pyodbc.connect('Driver={SQL Server};'
import pyodbc
def read_and_update_files_queue(self):
conn = pyodbc.connect('Driver={SQL Server};'
'Server='+self.server+';'
'Database='+self.database+';'
'Trusted_Connection=yes;')
cursor = conn.cursor()
sql_query=f'''
BEGIN TRANSACTION;
DECLARE @Temp_ID AS INT
SELECT TOP 1 @Temp_ID=Id
FROM dbo.[Queue]
WITH(XLOCK, ROWLOCK)
WHERE [BQ_status] IS NULL and upload_date IS NOT NULL
Select TOP 1
Id,GCS_path,file_first_upload
FROM dbo.[Queue]
WITH(XLOCK, ROWLOCK)
WHERE Id=@Temp_ID
UPDATE dbo.[Queue] SET BQ_status='Loading'
WHERE Id=@Temp_ID
COMMIT TRANSACTION;
'''
cursor.execute(sql_query)
cursor.commit()
怎么了?
该代码基于以下内容:
谢谢 因为前两条语句不是在修改数据,否则它在事务结束之前都不会持有锁,而不管是什么 但是您可以在一条语句中完成所有操作,这里不需要
UPDLOCK
,也不需要显式事务(该语句在事务中运行)
更新顶部(1)q
设置BQ_状态=‘加载’
输出inserted.Id、inserted.GCS\u路径、inserted.file\u首次上传
来自dbo。[Queue]作为q,带有(可序列化,行锁)
其中q.[BQ_status]为空,q.upload_date不为空;
虽然SERIALIZABLE
有时确实只接受共享S
锁,但这仅适用于SELECT
或DML语句中未修改的联接表
在本例中,由于Queue
是正在修改的表,因此在查找正确的行时会执行U
锁定,这将禁止U
锁定其他事务,这些事务将在等待时被阻止(仅执行SELECT
的事务不会被阻止)。然后,当一行即将被修改时,U
锁被升级为X
,并被修改
因此,这里不必担心竞争条件,也不必使用
UPDLOCK
提示。帮自己一个大忙,在SQLSERVER上的存储过程中使用TRY-CATCH和回滚来处理此事务。在seconds语句中,我不仅需要返回ID,还需要返回名为GCS_path、file_first_upload的字段,这些字段稍后将在python程序中使用。为什么需要试一试?(如果我在不存在ID的情况下运行此事务,它将按预期工作(它不执行任何操作)),然后使用第一个select语句执行该操作。只需为GCS_path声明变量,首先上传文件,并捕获其中的值,以便稍后在python程序中重用。删除第二个select语句。谢谢。这很有效。但据我所知,Serializable创建了一个共享锁,所以其他进程仍然可以读取该行,还是我错了?我认为为了避免竞争条件,锁应该是独占锁而不是共享锁。不,这只适用于未修改的表,否则将使用U
锁,这将阻止其他修改器。除非修改表,否则不能强制执行X
锁定。已经澄清。